<!DOCTYPE html><!-- ###BEGIN###{EventSubscriptions} --><!-- ###END###{EventSubscriptions} --><!-- ###BEGIN###{Desktop-Settings} --><!-- ###END###{Desktop-Settings} --><!-- ###BEGIN###{Desktop-Multi} --><!-- ###END###{Desktop-Multi} --><!-- ###BEGIN###{ComputerSelectorNoImages} --><!-- ###END###{ComputerSelectorNoImages} --><!-- ###BEGIN###{ComputerSelector-Local-ScriptOnly} --><!-- ###END###{ComputerSelector-Local-ScriptOnly} --><html lang="it" style="height:100%"><head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta name="format-detection" content="telephone=no">
    <link rel="icon" type="image/png" href=""> <!-- Stop favicon.ico from loading -->
<!-- ###BEGIN###{Look-Commander} -->
    <!-- ###BEGIN###{ComputerSelector} -->
    <link type="text/css" href="styles-commander-node.css" media="screen" rel="stylesheet" title="CSS">
    <!-- ###END###{ComputerSelector} -->
    <!-- ###BEGIN###{!ComputerSelector} -->
    <link type="text/css" href="styles-commander.css" media="screen" rel="stylesheet" title="CSS">
    <!-- ###END###{!ComputerSelector} -->
<!-- ###END###{Look-Commander} -->
<!-- ###BEGIN###{Look-Branded} -->
    <link type="text/css" href="styles-branded.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-Branded} -->
<!-- ###BEGIN###{Look-ISDU} -->
    <link type="text/css" href="styles-isdu.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-ISDU} -->
<!-- ###BEGIN###{Look-BrandedCommander} -->
    <link type="text/css" href="styles-brandedcommander.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-BrandedCommander} -->
<!-- ###BEGIN###{Look-Unite} -->
    <link type="text/css" href="styles-unite.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-Unite} -->
<!-- ###BEGIN###{Look-MeshCentral} -->
    <link type="text/css" href="styles-mesh.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-MeshCentral} -->
    <script type="text/javascript" src="common-0.0.1.js"></script>
<!-- ###BEGIN###{Mode-LMS} -->
    <script type="text/javascript" src="amt-lms-0.0.1.js"></script>
    <script type="text/javascript" src="amt-wsman-ws-0.2.0.js"></script>
<!-- ###END###{Mode-LMS} -->
<!-- ###BEGIN###{Mode-NodeWebkit} -->
    <script type="text/javascript" src="amt-wsman-node-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-node-0.1.0.js"></script>
    <script type="text/javascript" src="amt-scanner-0.1.0.js"></script>
<!-- ###END###{Mode-NodeWebkit} -->
<!-- ###BEGIN###{Mode-WebSite} -->
    <script type="text/javascript" src="amt-wsman-ws-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-ws-0.1.0.js"></script>
<!-- ###END###{Mode-WebSite} -->
<!-- ###BEGIN###{Mode-Firmware} -->
    <script type="text/javascript" src="amt-wsman-ajax-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-ws-0.1.0.js"></script>
<!-- ###END###{Mode-Firmware} -->
<!-- ###BEGIN###{IDER} -->
    <script type="text/javascript" src="amt-ider-ws-0.0.1.js"></script>
    <!-- ###BEGIN###{IDER-IMRSDK} -->
    <script type="text/javascript" src="amt-ider-node-0.0.1.js"></script>
    <!-- ###END###{IDER-IMRSDK} -->
    <!-- ###BEGIN###{Mode-MeshCentral2} -->
    <script type="text/javascript" src="amt-ider-server-ws-0.0.1.js"></script>
    <!-- ###END###{Mode-MeshCentral2} -->
<!-- ###END###{IDER} -->
<!-- ###BEGIN###{Mode-MeshCentral2} -->
    <script type="text/javascript" src="amt-wsman-ws-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-ws-0.1.0.js"></script>
<!-- ###END###{Mode-MeshCentral2} -->
    <script type="text/javascript" src="amt-wsman-0.2.0.js"></script>
    <script type="text/javascript" src="amt-0.2.0.js"></script>
<!-- ###BEGIN###{Certificates} -->
    <script type="text/javascript" src="forge.js/forge.bundle.js"></script>
    <script type="text/javascript" src="amt-certificates-0.0.1.js"></script>
<!-- ###END###{Certificates} -->
<!-- ###BEGIN###{Scripting} -->
    <script type="text/javascript" src="amt-script-0.2.0.js"></script>
<!-- ###END###{Scripting} -->
<!-- ###BEGIN###{Desktop} -->
    <script type="text/javascript" src="amt-desktop-0.0.2.js"></script>
    <style type="text/css">
        .rb { cursor: pointer; border: none; float: right; font-size: 130%; margin-right: 4px; }
    </style>
<!-- ###END###{Desktop} -->
<!-- ###BEGIN###{DesktopInband} -->
    <script type="text/javascript" src="agent-desktop-0.0.2.js"></script>
    <script type="text/javascript" src="agent-redir-rtc-0.1.0.js"></script>
<!-- ###END###{DesktopInband} -->
<!-- ###BEGIN###{Terminal} -->
    <script type="text/javascript" src="amt-terminal-0.0.2.js"></script>
<!-- ###END###{Terminal} -->
<!-- ###BEGIN###{PowerControl-Advanced} -->
<!-- ###BEGIN###{PowerControl-OneClick} -->
    <script type="text/javascript" src="webserver-0.0.1.js"></script>
<!-- ###END###{PowerControl-Advanced} -->
<!-- ###END###{PowerControl-OneClick} -->
<!-- ###BEGIN###{Inflate} -->
    <script type="text/javascript" src="zlib.js"></script>
    <script type="text/javascript" src="zlib-inflate.js"></script>
    <script type="text/javascript" src="zlib-adler32.js"></script>
    <script type="text/javascript" src="zlib-crc32.js"></script>
<!-- ###END###{Inflate} -->
<!-- ###BEGIN###{USBSetup} -->
    <script type="text/javascript" src="amt-setupbin-0.1.0.js"></script>
<!-- ###END###{USBSetup} -->
<!-- ###BEGIN###{FileSaver} -->
    <script type="text/javascript" src="filesaver.1.1.20151003.js"></script>
<!-- ###END###{FileSaver} -->
<!-- ###BEGIN###{MeshServerConnect} -->
    <script type="text/javascript" src="meshcentral-server-0.2.0.js"></script>
    <script type="text/javascript" src="websocket-wrapper-0.2.0.js"></script>
<!-- ###END###{MeshServerConnect} -->
<!-- ###BEGIN###{Mode-LMS} -->
    <style type="text/css">
        .menuitem { cursor: pointer; border: none; padding:5px; }
        .menuitem:hover { background-color: #6b9dc7; }
    </style>
<!-- ###END###{Mode-LMS} -->
<!-- ###BEGIN###{ComputerSelector} -->
    <style type="text/css">
        .menuitem { cursor: pointer; border: none; padding:5px; }
        .menuitem:hover { background-color: #6b9dc7; }
    </style>
<!-- ###END###{ComputerSelector} -->
<!-- ###BEGIN###{ContextMenus} -->
    <style>
        .contextMenu {
            background: #F9F9F9;
            box-shadow: 0 0 12px rgba( 0, 0, 0, .3 );
            border: 1px solid #ccc;
            /*border-radius: 4px;*/
            position: absolute;
            top: 0;
            left: 0;
            list-style: none;
            margin: 0;
            padding: 5px;
            min-width: 100px;
            max-width: 150px;
            z-index: 500;
        }

        .cmtext {
            color: #444;
            display: inline-block;
            padding-left: 8px;
            padding-right: 8px;
            padding-top: 5px;
            padding-bottom: 5px;
            text-decoration: none;
            width: 85%;
            cursor: default;
            overflow: hidden;
            position: relative;
        }

            .cmtext:hover {
                color: #f9f9f9;
                background: #999;
            }
    </style>
<!-- ###END###{ContextMenus} -->
<!-- ###BEGIN###{DesktopInbandFiles} -->
    <style>
        .fileIcon1 {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            float: left;
            margin-top: 1px;
        }

        .fileIcon2 {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            float: left;
            margin-top: 1px;
        }

        .fileIcon3 {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            float: left;
            margin-top: 1px;
        }

        .filelist {
            -moz-user-select: none;
            -khtml-user-select: none;
            -webkit-user-select: none;
            -o-user-select: none;
            cursor: default;
            -khtml-user-drag: element;
            background-color: white;
            clear: both;
        }

        .fsize {
            float: right;
            text-align: right;
            width: 180px;
        }
    </style>
<!-- ###END###{DesktopInbandFiles} -->
<!-- ###BEGIN###{SessionRecording} -->
    <style>
        .cameraIcon {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            margin-top:2px;
            margin-right:4px;
            cursor:pointer;
            float:right;
        }

        .videoIcon {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            margin-top:2px;
            margin-right:4px;
            cursor:pointer;
            float:right;
        }

        .videoIconRed {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            margin-top:2px;
            margin-right:4px;
            cursor:pointer;
            float:right;
        }
    </style>
<!-- ###END###{SessionRecording} -->
<!-- ###BEGIN###{Look-Commander} -->
    <!-- ###BEGIN###{!ComputerSelector-Local-ScriptOnly} -->
    <!-- ###BEGIN###{!Mode-LMS} -->
    <title>MeshCommander</title>
    <!-- ###END###{!Mode-LMS} -->
    <!-- ###BEGIN###{Mode-LMS} -->
    <title>LMS MeshCommander</title>
    <!-- ###END###{Mode-LMS} -->
    <!-- ###END###{!ComputerSelector-Local-ScriptOnly} -->
    <!-- ###BEGIN###{ComputerSelector-Local-ScriptOnly} -->
    <title>ScriptCommander</title>
    <!-- ###END###{ComputerSelector-Local-ScriptOnly} -->
<!-- ###END###{Look-Commander} -->
<!-- ###BEGIN###{Look-Branded} -->
    <title>Intel® Active Management Technology</title>
<!-- ###END###{Look-Branded} -->
<!-- ###BEGIN###{Look-ISDU} -->
    <title>Intel® System Defense Utility</title>
<!-- ###END###{Look-ISDU} -->
<!-- ###BEGIN###{Look-BrandedCommander} -->
    <title>Intel® Manageability Commander</title>
<!-- ###END###{Look-BrandedCommander} -->
<!-- ###BEGIN###{Look-Unite} -->
    <title>Intel® Unite - Hardware Management</title>
<!-- ###END###{Look-Unite} -->
</head>
<!-- ###BEGIN###{!ContextMenus} -->
<body onunload="cleanup()" oncontextmenu="handleContextMenu(event)">
<!-- ###END###{!ContextMenus} -->
<!-- ###BEGIN###{ContextMenus} -->

<!-- ###END###{ContextMenus} -->
    <div id="id_topheader" class="header">
        <!-- ###BEGIN###{!Look-MeshCentral} -->
        <!-- ###BEGIN###{Look-Unite} -->
        <table style="width:100%;height:55px">
            <tbody><tr>
                <td valign="top" nowrap="nowrap">
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Active Management Technology</p>
                    <p class="top2" id="id_computername"></p>
                </td>
                <td valign="top">
                    <img width="165" height="42" align="right" style="border:0;margin-top:10px;margin-right:12px" src="images-unite/title.png">
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{Look-Unite} -->
        <!-- ###BEGIN###{Look-ISDU} -->
        <div>
            <div style="background-image:url(images-isdu/LogoWhite42.png);width:63px;height:42px;float:right;margin-top:14px;margin-right:20px;padding:0"></div>
            <div style="width:425px;height:69px"><div style="background-image:url(images-isdu/ISDUTitle.png);position:relative;top:26px;left:20px;width:282px;height:20px"></div></div>
            <p id="id_computername" style="display:none"></p>
        </div>
        <!-- ###END###{Look-ISDU} -->
        <!-- ###BEGIN###{Look-BrandedCommander} -->
        <!-- ###BEGIN###{Mode-NodeWebkit} -->
        <div>
            <div style="background-image:url(images-brandedcommander/LogoWhite42.png);width:63px;height:42px;float:right;margin-top:14px;margin-right:20px;padding:0"></div>
            <div style="width:425px;height:69px"><div style="background-image:url(images-brandedcommander/CommanderTitle.png);position:relative;top:21px;left:20px;width:443px;height:33px"></div></div>
            <p id="id_computername" style="display:none"></p>
        </div>
        <!-- ###END###{Mode-NodeWebkit} -->
        <!-- ###BEGIN###{!Mode-NodeWebkit} -->
        <table style="width:100%;height:55px">
            <tbody><tr>
                <td valign="top" nowrap="nowrap">
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Manageability Commander</p>
                    <p class="top2" id="id_computername"></p>
                </td>
                <td valign="top">
                    <img width="73" height="53" align="right" style="border:0" src="images-branded/logo.gif">
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{!Mode-NodeWebkit} -->
        <!-- ###END###{Look-BrandedCommander} -->
        <!-- ###BEGIN###{!Look-ISDU} -->
        <!-- ###BEGIN###{!Look-BrandedCommander} -->
        <table class="topCell" style="width:100%;height:55px">
            <tbody><tr>
                <td valign="top" nowrap="nowrap">
                    <!-- ###BEGIN###{Look-Commander} -->
                    <!-- ###BEGIN###{Switchbox} -->
                    <p class="top1">Manageability Switchbox</p>
                    <!-- ###END###{Switchbox} -->
                    <!-- ###BEGIN###{!Switchbox} -->
                    <!-- ###BEGIN###{!ComputerSelector-Local-ScriptOnly} -->

                    <!-- ###BEGIN###{!Mode-LMS} -->
                    <p class="top1">MeshCommander</p>
                    <!-- ###END###{!Mode-LMS} -->
                    <!-- ###BEGIN###{Mode-LMS} -->
                    <p class="top1">LMS MeshCommander</p>
                    <!-- ###END###{Mode-LMS} -->
                    <!-- ###END###{!ComputerSelector-Local-ScriptOnly} -->
                    <!-- ###BEGIN###{ComputerSelector-Local-ScriptOnly} -->
                    <p class="top1">ScriptCommander</p>
                    <!-- ###END###{ComputerSelector-Local-ScriptOnly} -->
                    <!-- ###END###{!Switchbox} -->
                    <!-- ###END###{Look-Commander} -->
                    <!-- ###BEGIN###{Look-Intel-AMT} -->
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Active Management Technology</p>
                    <!-- ###END###{Look-Intel-AMT} -->
                    <!-- ###BEGIN###{Look-Intel-SM} -->
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Standard Manageability</p>
                    <!-- ###END###{Look-Intel-SM} -->
                    <!-- ###BEGIN###{Look-Intel-SBT} -->
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Small Buisness Technology</p>
                    <!-- ###END###{Look-Intel-SBT} -->
                    <p class="top2" id="id_computername"></p>
                </td>
                <td valign="top">
                    <!-- ###BEGIN###{!Mode-LMS} -->
                    <!-- ###BEGIN###{!Mode-Firmware} -->
                    <!-- ###BEGIN###{Look-Commander} -->
                    <img width="166" height="64" align="right" style="border:0" src="images-commander/logo.png">
                    <!-- ###END###{Look-Commander} -->
                    <!-- ###END###{!Mode-Firmware} -->
                    <!-- ###END###{!Mode-LMS} -->
                    <!-- ###BEGIN###{Look-Branded} -->
                    <img width="73" height="53" align="right" style="border:0" src="images-branded/logo.gif">
                    <!-- ###END###{Look-Branded} -->
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{!Look-BrandedCommander} -->
        <!-- ###END###{!Look-ISDU} -->
        <!-- ###END###{!Look-MeshCentral} -->
        <!-- ###BEGIN###{Mode-MeshCentral2} -->
        <table id="id_KVMTable" cellpadding="0" cellspacing="0" style="width: 100%; padding: 0px; padding: 0px; margin-top: 0px">
            <tbody><tr>
                <td id="id_normalScreenToolbar" class="style6">
                    <div>
                        &nbsp;<input type="button" class="connectbutton" id="xconnectbutton1" value="Collegare" onclick="connectButtonfunction(event, false)" onkeypress="return false" onkeydown="return false">
                        &nbsp;<span id="constatus"></span>
                    </div>
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{Mode-MeshCentral2} -->
        <div class="progressbar">
            <!-- ###BEGIN###{Look-MeshCentral} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-MeshCentral} -->
            <!-- ###BEGIN###{Look-Commander} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-Commander} -->
            <!-- ###BEGIN###{Look-Branded} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:orange"></div>
            <!-- ###END###{Look-Branded} -->
            <!-- ###BEGIN###{Look-ISDU} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-ISDU} -->
            <!-- ###BEGIN###{Look-BrandedCommander} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-BrandedCommander} -->
            <!-- ###BEGIN###{Look-Unite} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-Unite} -->
        </div>
    </div>
    <div id="id_messageview" class="fullcell" style="text-align:center;padding-top:100px;font-size:20px">
        <!-- ###BEGIN###{Look-MeshCentral} -->
        <span id="id_messageviewstr">Disconnected</span>
        <!-- ###END###{Look-MeshCentral} -->
        <!-- ###BEGIN###{!Look-MeshCentral} -->
        <span id="id_messageviewstr">Caricamento in corso...</span>
        <!-- ###END###{!Look-MeshCentral} -->
        <!-- ###BEGIN###{ComputerSelector} -->
        <br><br><input id="id_messageviewbutton" type="button" value="Vicino" onclick="disconnect()">
        <!-- ###END###{ComputerSelector} -->
        <!-- ###BEGIN###{Mode-LMS} -->
        <br><br><input type="button" value="Vicino" onclick="disconnect()">
        <!-- ###END###{Mode-LMS} -->
    </div>
    <!-- ###BEGIN###{Mode-LMS} -->
    <div id="id_lmsMainPanel" class="fullcell" style="display:none">
        <div style="background-color:lightgray;height:24px;margin-bottom:6px;padding-top:2px">
            <div id="id_lmsToolBarContent" style="display:none">
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <div style="float:left;height:26px;width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </div>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <div>
                    <input type="button" value="ricaricare" onclick="lmsRefresh()">
                    <input id="id_lmsActivateButton" type="button" value="Activate..." style="display:none" onclick="lmsActivate()">
                    <input id="id_lmsDeactivateButton" type="button" value="Deactivate..." style="display:none" onclick="lmsDeactivate()">
                    <input id="id_lmsLoginButton" type="button" value="Login..." style="display:none" onclick="lmsLogin()">
                    <input id="id_lmsConfigureButton" type="button" value="Intel® AMT Login..." style="display:none" onclick="lmsConfigure()">
                </div>
            </div>
        </div>
        <div id="id_lmsData" style="margin:10px"></div>
        <div id="id_lmsData2" style="margin:10px"></div>
    </div>
    <!-- ###END###{Mode-LMS} -->
    <!-- ###BEGIN###{PowerControl-OneClick} -->
    <div id="TransferNotification" style="display:none;background-color:lightgrey;position:absolute;left:10px;bottom:10px;border-radius:5px;padding:4px;z-index:1000;box-shadow:0px 0px 10px #333"></div>
    <!-- ###END###{PowerControl-OneClick} -->
    <!-- ###BEGIN###{Mode-NodeWebkit} -->
    <div id="LeftSideToolBar" style="position:absolute;left:0px;bottom:0px;width:52px;top:69px;background:#113962;background:linear-gradient(to bottom, #104893 0%,#113962 100%);color:white;display:none">
        <div style="height:23px"></div>
        <div id="LeftMenuMyDevices" class="lbbutton lbbuttonsel2" title="Gestione informatica" onclick="go(101)">
            <div class="lb1" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <div id="LeftMenuMyCerts" class="lbbutton" title="Gestione certificati" onclick="go(103)">
            <div class="lb2" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <div id="LeftMenuMyUsb" class="lbbutton" title="Manager Setup.bin" onclick="go(102)">
            <div class="lb3" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <!-- ###BEGIN###{SessionRecording} -->
        <div id="LeftMenuPlayer" class="lbbutton" title="Session Player" onclick="go(104)">
            <div class="lb4" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <!-- ###END###{SessionRecording} -->
    </div>
    <!-- ###END###{Mode-NodeWebkit} -->
    <!-- ###BEGIN###{ComputerSelector} -->
    <div id="id_computerSelector" class="fullcell" style="display:none">
        <!-- ###BEGIN###{Mode-NodeWebkit} -->
        <div id="UpdateNotification" style="display:none;background-color:lightgrey;position:absolute;left:10px;bottom:10px;border-radius:5px;padding:10px;z-index:1000;box-shadow: 0px 0px 20px #888888">
            <a style="cursor:pointer;color:blue" onclick="NW_PerformUpdate()"><u id="UpdateNotificationText"></u></a> &nbsp; <span onclick="NW_HideUpdateNotification()" style="cursor:pointer;font-size:15px">✖</span>
        </div>
        <!-- ###END###{Mode-NodeWebkit} -->
        <!-- ###BEGIN###{ComputerSelectorToolbar} -->
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td id="toolmenuicondiv" style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <!-- ###BEGIN###{MeshServerConnect} -->
                <td id="idx_disconnectMeshCentralButton" style="display:none">
                    <input type="button" value="Disconnect" onclick="meshCentralDisconnect()">
                </td>
                <!-- ###END###{MeshServerConnect} -->
                <td>
                    <span id="id_noScriptButtons">
                        <!-- ###BEGIN###{ComputerSelector-Remote} -->
                        <input type="button" value="ricaricare" onclick="loadServerComputerList()">
                        <!-- ###END###{ComputerSelector-Remote} -->
                        <!-- ###BEGIN###{ComputerSelector-Local} -->
                        <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                        <input type="button" value="Nuovo..." onclick="newComputerList()">
                        <input type="button" value="Aperto..." onclick="openComputerList()">
                        <!-- ###BEGIN###{FileSaver} -->
                        <input id="saveComputersButton" type="button" value="Salva..." onclick="saveComputerList()">
                        <!-- ###END###{FileSaver} -->
                        <!-- ###END###{!Mode-NodeWebkit} -->
                        <input type="button" value="Aggiungi computer ..." onclick="addComputer()">
                        <!-- ###END###{ComputerSelector-Local} -->
                        <!-- ###BEGIN###{ComputerSelectorScanner} -->
                        <!-- ###BEGIN###{Mode-NodeWebkit} -->
                        <input type="button" value="Scansione..." onclick="showScanDialog()">
                        <!-- ###END###{Mode-NodeWebkit} -->
                        <!-- ###END###{ComputerSelectorScanner} -->
                    </span>
                    <!-- ###BEGIN###{Scripting} -->
                    <!-- ###BEGIN###{!Look-BrandedCommander} -->
                    <input id="idx_runScriptOnComputersButton" type="button" value="Esegui script ..." onclick="mscript_runScriptDlg()">
                    <!-- ###END###{!Look-BrandedCommander} -->
                    <!-- ###BEGIN###{Look-BrandedCommander} -->
                    <input id="idx_runScriptOnComputersButton" type="button" value="Esegui script ..." onclick="mscript_runScriptDlg()" style="display:none">
                    <!-- ###END###{Look-BrandedCommander} -->
                    <!-- ###END###{Scripting} -->
                </td>
                <td style="text-align:right">
                    <!-- ###BEGIN###{!Look-BrandedCommander} -->
                    <input id="computerFilter" placeholder="Filtro" onkeyup="computerFilterFunc()" autocomplete="off" onfocus="onFilterFocus(true)" onblur="onFilterFocus(false)">
                    <!-- ###END###{!Look-BrandedCommander} -->
                </td>
            </tr>
        </tbody></table>
        <!-- ###BEGIN###{ComputerSelector-Local} -->
        <div id="id_computerListParent" style="position:fixed;top:96px;left:0;right:300px;bottom:0;overflow-y:scroll" cm="Add&nbsp;Computer...#addComputer()">
        <!-- ###END###{ComputerSelector-Local} -->
        <!-- ###BEGIN###{!ComputerSelector-Local} -->
            <div id="id_computerListParent" style="position:fixed;top:96px;left:0;right:300px;bottom:0;overflow-y:scroll">
        <!-- ###END###{!ComputerSelector-Local} -->
                <div id="id_noKnownComputers" style="text-align:center;margin-top:36px;color:gray">
                    <span style="font-size:20px">Nessun computer noto</span>
                    <!-- ###BEGIN###{ComputerSelector-Local} -->
                    <div style="margin:4px">Inizia da <a onclick="addComputer()" style="cursor:pointer"><u>aggiungendo</u></a> computer o trascinamento della selezione<br>un file dell'elenco dei computer in questa finestra.</div>
                    <!-- ###END###{ComputerSelector-Local} -->
                </div>
                <div id="id_computerList" style="font-size:20px"></div>
            </div>
        <div id="id_computerDetailsParent" style="position:fixed;top:96px;width:300px;right:0;bottom:0">
            <div id="id_computerDetails" style="font-size:16px;margin:4px"></div>
        </div>
        <!-- ###END###{ComputerSelectorToolbar} -->
        <!-- ###BEGIN###{!ComputerSelectorToolbar} -->
        <div id="id_computerListParent" style="position:fixed;top:69px;left:0;right:300px;bottom:0;overflow-y:scroll" cm="Add&nbsp;Computer...#addComputer()">
            <div id="id_noKnownComputers" style="text-align:center;margin-top:36px;color:gray">
                <span style="font-size:20px">Nessun computer noto</span>
                <!-- ###BEGIN###{ComputerSelector-Local} -->
                <div style="margin:4px">Inizia da <a onclick="addComputer()" style="cursor:pointer"><u>aggiungendo</u></a> computer o trascinamento della selezione<br>un file dell'elenco dei computer in questa finestra.</div>
                <!-- ###END###{ComputerSelector-Local} -->
            </div>
            <div id="id_computerList" style="font-size:20px"></div>
        </div>
        <div id="id_computerDetailsParent" style="position:fixed;top:69px;width:300px;right:0;bottom:0;background-color:white">
            <div id="id_computerDetails" style="font-size:16px;margin:8px"></div>
        </div>
        <!-- ###END###{!ComputerSelectorToolbar} -->
    </div>
    <div id="id_computerSelectorMenu" style="background-color:#EEEEEE;display:none;position:absolute;left:0;top:94px;width:200px;padding:3px;z-index:1000;box-shadow:5px 5px 5px #888888;border:1px solid gray">
        <div class="menuitem" onclick="toolmenuclick(101)"><span id="id_menuitem1">• </span>Gestione informatica</div>
        <!-- ###BEGIN###{CertificateManager} -->
        <div class="menuitem" onclick="toolmenuclick(103)"><span id="id_menuitem3" style="display:none">• </span>Gestione certificati</div>
        <!-- ###END###{CertificateManager} -->
        <!-- ###BEGIN###{USBSetup} -->
        <div class="menuitem" onclick="toolmenuclick(102)"><span id="id_menuitem2" style="display:none">• </span>Editor USB Setup.bin</div>
        <!-- ###END###{USBSetup} -->
        <!-- ###BEGIN###{SessionRecording} -->
        <div class="menuitem" onclick="toolmenuclick(104)"><span id="id_menuitem4" style="display:none">• </span>Session Player</div>
        <!-- ###END###{SessionRecording} -->
    </div>
    <!-- ###END###{ComputerSelector} -->
    <!-- ###BEGIN###{Mode-LMS} -->
    <div id="id_computerSelectorMenu" style="background-color:#EEEEEE;display:none;position:absolute;left:0;top:94px;width:200px;padding:3px;z-index:1000;box-shadow:5px 5px 5px #888888;border:1px solid gray">
        <div class="menuitem" onclick="toolmenuclick(101)"><span id="id_menuitem1">• </span>Computer Configuration</div>
        <!-- ###BEGIN###{USBSetup} -->
        <div class="menuitem" onclick="toolmenuclick(102)"><span id="id_menuitem2" style="display:none">• </span>Editor USB Setup.bin</div>
        <!-- ###END###{USBSetup} -->
    </div>
    <!-- ###END###{Mode-LMS} -->
    <!-- ###BEGIN###{USBSetup} -->
    <div id="id_usbSetupPanel" class="fullcell" style="display:none">
        <!-- ###BEGIN###{ComputerSelectorToolbar} -->
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <td>
                    <input type="button" value="Nuovo..." onclick="usb_newSetupBin()">
                    <input type="button" value="Aperto..." onclick="usb_openSetupBin()">
                    <!-- ###BEGIN###{FileSaver} -->
                    <input id="id_saveSetupBin" type="button" value="Salva..." onclick="usb_saveSetupBin()">
                    <!-- ###END###{FileSaver} -->
                </td>
            </tr>
        </tbody></table>
        <div id="id_usbSetupPanel2" style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:96px">
            <div id="id_StartupScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Intel<sup style="font-size:10px">®</sup> Gestione AMT USB Setup.bin</span>
                <div style="margin:4px">Inizia da <a onclick="usb_newSetupBin()" style="cursor:pointer"><u>la creazione di</u></a> un nuovo file, <a onclick="usb_openSetupBin()" style="cursor:pointer"><u>apertura</u></a> uno esistente<br>oppure trascina e rilascia un file setup.bin in questa finestra.</div>
            </div>
            <div id="id_SetupBinArea" style="margin:10px"></div>
        </div>
        <!-- ###END###{ComputerSelectorToolbar} -->
        <!-- ###BEGIN###{!ComputerSelectorToolbar} -->
        <div style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:69px">
            <div id="id_StartupScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Intel<sup style="font-size:10px">®</sup> Gestione AMT USB Setup.bin</span>
                <div style="margin:4px">Inizia da <a onclick="usb_newSetupBin()" style="cursor:pointer"><u>la creazione di</u></a> un nuovo file, <a onclick="usb_openSetupBin()" style="cursor:pointer"><u>apertura</u></a> uno esistente<br>oppure trascina e rilascia un file setup.bin in questa finestra.</div>
            </div>
            <div id="id_SetupBinArea" style="margin:10px"></div>
        </div>
        <!-- ###END###{!ComputerSelectorToolbar} -->
    </div>
    <!-- ###END###{USBSetup} -->
    <!-- ###BEGIN###{CertificateManager} -->
    <div id="id_certManagerPanel" class="fullcell" style="display:none">
        <!-- ###BEGIN###{ComputerSelectorToolbar} -->
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <td>
                    <input type="button" value="Crea certificato radice ..." onclick="cert_createNew()">
                    <input id="IssueCertButton" type="button" value="Rilascia certificato ..." onclick="cert_issueNew()">
                    <input type="button" value="Certificato di importazione ..." onclick="cert_importCert()">
                </td>
            </tr>
        </tbody></table>
        <div id="id_certManagerPanel2" style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:96px">
            <div id="id_certStartScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Gestione certificati</span>
                <div style="margin:4px">I certificati svolgono un ruolo importante in tutti i tipi di attività di sicurezza Intel® AMT: autenticazione di rete TLS,<br>Configurazione CIRA, firma del registro di controllo e altro. Utilizzare questo pannello per creare e gestire il certificato della console.</div>
            </div>
            <div id="id_certManagerMainArea" style="font-size:20px"></div>
            <!-- ###BEGIN###{Mode-NodeWebkit} -->
            <input id="certOpenFile" type="file" style="display:none" accept=".cer;*.pfx;*.p12;*.pem;*.crt">
            <!-- ###END###{Mode-NodeWebkit} -->
        </div>
        <!-- ###END###{ComputerSelectorToolbar} -->
        <!-- ###BEGIN###{!ComputerSelectorToolbar} -->
        <div style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:95px">
            <div id="id_certStartScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Gestione certificati</span>
                <div style="margin:4px">I certificati svolgono un ruolo importante in tutti i tipi di attività di sicurezza Intel® AMT: autenticazione di rete TLS,<br>Configurazione CIRA, firma del registro di controllo e altro. Utilizzare questo pannello per creare e gestire il certificato della console.</div>
            </div>
            <div id="id_certManagerMainArea" style="margin:10px"></div>
        </div>
        <!-- ###END###{!ComputerSelectorToolbar} -->
    </div>
    <!-- ###END###{CertificateManager} -->
    <!-- ###BEGIN###{SessionRecording} -->
    <div id="id_sessionPlayerPanel" class="fullcell" style="display:none">
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <td>
                    <div style="float:right">
                        <input id="srec_toggleviewmode" type="button" value="Attiva / disattiva modalità di visualizzazione" style="display:none" onclick="srec_toggleAspectRatio(1)">
                    </div>
                    <input type="button" id="srec_OpenFileButton" value="Apri il file..." onclick="srec_openfile()">
                    <span id="srec_deskstatus" style="margin-left:4px"></span>
                </td>
            </tr>
        </tbody></table>
        <div style="overflow:hidden">
            <div id="srec_deskarea0">
                <div id="srec_deskarea2" style="height:2px">
                    <div style="background-color:gray"><div id="srec_progressbar" style="height:2px;width:0%;background-color:red"></div></div>
                </div>
                <div id="srec_deskarea3x" style="position:relative;max-height:calc(100vh - 123px);height:calc(100vh - 123px)" onclick="srec_togglePause()">
                    <div id="srec_metadatadiv" style="padding:20px;color:lightgrey;text-align:left;display:none"></div>
                    <div id="srec_DeskParent" style="width:100%;height:100%;background-color:black;display:none">
                        <canvas id="srec_Desk" width="640" height="480"></canvas>
                    </div>
                    <div id="srec_TermParent" style="position:absolute;top:0;height:100%;width:100%;background-color:black;display:none">
                        <div><pre id="srec_Term"></pre></div>
                    </div>
                    <!--<div id=srec_p11DeskConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=clearConsoleMsg()></div>-->
                </div>
                <div id="srec_deskarea4" style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
                    <div style="float:right;text-align:right;padding-right:4px">
                        <div id="srec_timespan" style="padding-top:4px;padding-right:4px">00:00:00</div>
                    </div>
                    <div>
                        &nbsp;
                        <input id="srec_PlayButton" type="button" value="Giocare" disabled="disabled" onclick="srec_play()">
                        <input id="srec_PauseButton" type="button" value="Pausa" disabled="disabled" onclick="srec_pause()">
                        <input id="srec_RestartButton" type="button" value="Ricomincia" disabled="disabled" onclick="srec_restart()">
                        <select id="srec_PlaySpeed" onchange="this.blur();">
                            <option value="4">1/4 di velocità</option>
                            <option value="2">1/2 velocità</option>
                            <option value="1" selected="">Velocità normale</option>
                            <option value="0.5">2x velocità</option>
                            <option value="0.25">4x velocità</option>
                            <option value="0.1">10x Speed</option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- ###END###{SessionRecording} -->
    <div id="id_mainview" style="height:100%;display:none">
        <div id="id_leftbar" class="navbar">
            <!-- ###BEGIN###{Mode-NodeWebkit} -->
            <div id="tlsNotification1" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none" onclick="showTlsCert(1)"><img src="images/lock.gif"> TLS protetto</div>
            <div id="tlsNotification2" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none" onclick="showTlsCert(1)"><img src="images/lock.gif"> TLS protetto (appuntato)</div>
            <div id="tlsNotification3" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none" onclick="showTlsCert(1)"><img src="images/lock.gif"> TLS (non attendibile)</div>
            <div id="tlsNotification4" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none;color:red" onclick="switchToTls()"><img src="images/unlock.gif"> Passa a TLS</div>
            <!-- ###END###{Mode-NodeWebkit} -->
            <!-- ###BEGIN###{ComputerSelector} -->
            <div style="padding:8px">
                <input type="button" id="disconnectButton" value="Disconnect" onkeypress="return false" onkeydown="return false" onclick="disconnect()" style="width:138px">
            </div>
            <!-- ###END###{ComputerSelector} -->
            <!-- ###BEGIN###{Mode-LMS} -->
            <div style="padding:8px">
                <input type="button" id="disconnectButton" value="Disconnect" onkeypress="return false" onkeydown="return false" onclick="disconnect()" style="width:138px">
            </div>
            <!-- ###END###{Mode-LMS} -->
            <!-- ###BEGIN###{Mode-Firmware} -->
            <br>
            <!-- ###END###{Mode-Firmware} -->
            <!-- ###BEGIN###{Mode-MeshCentral2} -->
            <br>
            <!-- ###END###{Mode-MeshCentral2} -->
            <p id="go1" class="nav1" onclick="go(1)"><a>Stato del sistema</a></p>
            <!-- ###BEGIN###{Desktop} -->
            <p id="go14" class="nav1" onclick="go(14)"><a>Desktop remoto</a></p>
            <!-- ###BEGIN###{DesktopInbandFiles} -->
            <p id="go24" class="nav1" onclick="go(24)">&nbsp;&nbsp;<a>File</a></p>
            <!-- ###END###{DesktopInbandFiles} -->
            <!-- ###END###{Desktop} -->
            <!-- ###BEGIN###{Terminal} -->
            <p id="go13" class="nav1" onclick="go(13)"><a>Serial-over-LAN</a></p>
            <!-- ###END###{Terminal} -->
            <!-- ###BEGIN###{HardwareInfo} -->
            <p id="go2" class="nav1" onclick="go(2)"><a>Informazioni hardware</a></p>
            <!-- ###END###{HardwareInfo} -->
            <!-- ###BEGIN###{EventLog} -->
            <p id="go6" class="nav1" onclick="go(6)"><a>Registro eventi</a></p>
            <!-- ###END###{EventLog} -->
            <!-- ###BEGIN###{AuditLog} -->
            <p id="go15" class="nav1" onclick="go(15)"><a>Registro di audizione</a></p>
            <!-- ###END###{AuditLog} -->
            <!-- ###BEGIN###{Storage} -->
            <p id="go21" class="nav1" onclick="go(21)"><a>Conservazione</a></p>
            <!-- ###END###{Storage} -->
            <!-- ###BEGIN###{NetworkSettings} -->
            <p id="go8" class="nav1" onclick="go(8)"><a>Impostazioni di rete</a></p>
            <!-- ###END###{NetworkSettings} -->
            <!-- ###BEGIN###{RemoteAccess} -->
            <p id="go17" class="nav1" onclick="go(17)"><a>Impostazioni Internet</a></p>
            <!-- ###END###{RemoteAccess} -->
            <!-- ###BEGIN###{Certificates} -->
            <p id="go16" class="nav1" onclick="go(16)"><a>Impostazioni sicurezza</a></p>
            <!-- ###END###{Certificates} -->
            <!-- ###BEGIN###{AgentPresence} -->
            <p id="go19" class="nav1" onclick="go(19)"><a>Presenza agente</a></p>
            <!-- ###END###{AgentPresence} -->
            <!-- ###BEGIN###{SystemDefense} -->
            <p id="go18" class="nav1" onclick="go(18)"><a>Difesa del sistema</a></p>
            <!-- ###END###{SystemDefense} -->
            <p id="go11" class="nav1" onclick="go(11)"><a>Profili utente</a></p>
            <!-- ###BEGIN###{EventSubscriptions} -->
            <p id="go22" class="nav1" onclick="go(22)"><a>Sottoscrizioni</a></p>
            <!-- ###END###{EventSubscriptions} -->
            <!-- ###BEGIN###{Alarms} -->
            <p id="go23" class="nav1" onclick="go(23)"><a>Wake Alarms</a></p>
            <!-- ###END###{Alarms} -->
            <!-- ###BEGIN###{Scripting-Editor} -->
            <p id="go20" class="nav1" onclick="go(20)"><a>Editor di script</a></p>
            <!-- ###END###{Scripting-Editor} -->
            <!-- ###BEGIN###{WsmanBrowser} -->
            <p id="go12" class="nav1" onclick="go(12)"><a>Browser WSMAN</a></p>
            <!-- ###END###{WsmanBrowser} -->
            <!-- ###BEGIN###{Storage} -->
            <!-- ###BEGIN###{Mode-Firmware} -->
            <!-- <div id=storagelinks style=margin-top:4px></div> -->
            <!-- ###END###{Mode-Firmware} -->
            <!-- ###END###{Storage} -->
            <!-- ###BEGIN###{Look-ISDU} -->
            <img id="id_isdu-image1" src="images-isdu/TabConfig.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image2" src="images-isdu/TabConnection.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image3" src="images-isdu/TabDesktop.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image4" src="images-isdu/TabDiscovery.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image5" src="images-isdu/TabEvents.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image6" src="images-isdu/TabNetwork.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image7" src="images-isdu/TabPolicies.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image8" src="images-isdu/TabRemote.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <!-- ###END###{Look-ISDU} -->
            <!-- ###BEGIN###{Look-BrandedCommander} -->
            <!-- ###BEGIN###{!Mode-Firmware} -->
            <img id="id_isdu-image1" src="images-BrandedCommander/TabConfig.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image2" src="images-BrandedCommander/TabConnection.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image3" src="images-BrandedCommander/TabDesktop.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image4" src="images-BrandedCommander/TabDiscovery.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image5" src="images-BrandedCommander/TabEvents.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image6" src="images-BrandedCommander/TabNetwork.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image7" src="images-BrandedCommander/TabPolicies.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image8" src="images-BrandedCommander/TabRemote.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <!-- ###END###{!Mode-Firmware} -->
            <!-- ###END###{Look-BrandedCommander} -->
        </div>
        <div id="id_mainarea" class="maincell">
            <!-- ###BEGIN###{IDER} -->
            <div id="id_iderstatus" style="position:relative;height:21px;background:#8fac8d;padding:5px;margin-bottom:1px;display:none;z-index:1000">
                <div style="float:right">
                    <input id="IDERDiskMapButton" type="button" value="Mappa del disco" onclick="iderToggleDiskMap()">
                    <input type="button" value="Interrompi sessione IDE-R" onclick="iderStop()">
                </div>
                <div style="font-size:16px;padding-top:2px">&nbsp;<span id="id_iderstatusstr"></span></div>
                <div id="iderHeatmap" style="z-index:1000;position:absolute;top:31px;right:8px;border:1px solid black;box-shadow: 0px 0px 10px;border-radius:5px;padding:8px;width:600px;background-color:#99CC99;display:none">
                    <div id="floppyHeatMap" style="display:none">
                        <div id="floppyHeatMapText" style="margin:2px">Floppy, i blocchi sono 512 byte.</div>
                        <canvas id="floppyHeatMapCanvas" width="600" height="0"></canvas>
                    </div>
                    <div id="cdromHeatMap" style="display:none">
                        <div id="cdromHeatMapText" style="margin:2px">CD-ROM, i blocchi sono 2048 byte.</div>
                        <canvas id="cdromHeatMapCanvas" width="600" height="0"></canvas>
                    </div>
                </div>
            </div>
            <!-- ###END###{IDER} -->
            <!-- ###BEGIN###{Scripting} -->
            <div id="id_scriptstatus" style="height:21px;background:#8fac8d;padding:5px;margin-bottom:1px;display:none;overflow:hidden">
                <div style="float:right"><input type="button" value="Stop Script" onclick="script_Stop()"></div>
                <div style="font-size:16px;padding-top:2px;overflow:hidden">&nbsp;<b>Esecuzione di script</b><span style="overflow:hidden" id="id_scriptstatusstr"></span></div>
            </div>
            <!-- ###END###{Scripting} -->
            <!-- ###BEGIN###{VersionWarning} -->
            <div id="id_versionWarning" style="height:21px;background:#8fac8d;padding:5px;margin-bottom:1px;display:none">
                <div style="font-size:16px;float:right;cursor:pointer;padding-right:5px;padding-left:5px;padding-top:2px;font-size:15px" onclick="QV('id_versionWarning', false)">✖</div>
                <!-- ###BEGIN###{Mode-NodeWebkit} -->
                <div style="font-size:14px;padding-top:2px">&nbsp;<b>Il firmware di questo computer dovrebbe essere aggiornato,&nbsp;<a style="cursor:pointer" onclick="require('nw.gui').Shell.openExternal('https://security-center.intel.com/advisory.aspx?intelid=INTEL-SA-00075&amp;languageid=en-fr')"><u>per favore controlla qui</u></a>.</b></div>
                <!-- ###END###{Mode-NodeWebkit} -->
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <div style="font-size:14px;padding-top:2px">&nbsp;<b>Il firmware di questo computer dovrebbe essere aggiornato,&nbsp;<a style="cursor:pointer" href="https://security-center.intel.com/advisory.aspx?intelid=INTEL-SA-00075&amp;languageid=en-fr" rel="noreferrer noopener" target="_blank"><u>per favore controlla qui</u></a>.</b></div>
                <!-- ###END###{!Mode-NodeWebkit} -->
            </div>
            <!-- ###END###{VersionWarning} -->
            <!-- ###BEGIN###{Storage} -->
            <div id="id_mainarea_frame" style="width:100%;height:100%">
                <iframe id="id_StorageIFrame" style="width:100%;height:100%;border:0"></iframe>
            </div>
            <!-- ###END###{Storage} -->
            <div id="id_mainarea_pad" style="padding:8px;overflow-x:hidden">
                <div id="p0">
                    <h1>Caricamento in corso...</h1>
                </div>
                <div id="p1" style="display:none">
                    <h1>Stato del sistema</h1>
                    <span id="id_TableSysStatus"></span>
                </div>
                <!-- ###BEGIN###{HardwareInfo} -->
                <div id="p2" style="display:none">
                    <h1 style="margin-bottom:16px">Informazioni hardware</h1>
                    <span id="id_TableSysInfo"></span>
                </div>
                <!-- ###END###{HardwareInfo} -->
                <!-- ###BEGIN###{EventLog} -->
                <div id="p6" style="display:none">
                    <h1>Registro eventi</h1>
                    <span id="id_TableEventLog"></span>
                    <span id="id_TableEventLog2"></span>
                </div>
                <!-- ###END###{EventLog} -->
                <!-- ###BEGIN###{NetworkSettings} -->
                <div id="p8" style="display:none">
                    <h1>Impostazioni di rete</h1>
                    <span id="id_TableNetworkSettingsSpan"></span>
                    <!-- ###BEGIN###{Wireless} -->
                    <span id="id_TableWifi2"></span>
                    <!-- ###END###{Wireless} -->
                    <!-- ###BEGIN###{NetAuth} -->
                    <span id="id_TableNetAuth"></span>
                    <!-- ###END###{NetAuth} -->
                </div>
                <!-- ###END###{NetworkSettings} -->
                <div id="p11" style="display:none">
                    <h1>Profili utente</h1>
                    <span id="id_TableUserAccounts"></span>
                </div>
                <!-- ###BEGIN###{WsmanBrowser} -->
                <div id="p12" style="display:none">
                    <h1>Browser WSMAN</h1>
                    <div>
                        <table class="log1" cellpadding="0" cellspacing="0" style="width:100%;border-radius:8px">
                            <tbody><tr>
                                <td>
                                    <div style="padding:4px">
                                        <select id="id_QuerySelect" multiple="multiple" style="width:100%;height:120px"></select>
                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <input id="id_p12querybutton" type="button" value="domanda" style="margin: 4px" onclick="wsmanQuery()">
                                    <input type="button" value="Chiaro" style="margin: 4px" onclick="QH('id_wsresults', '')">
                                    <input id="idx_browserFilter" placeholder="Filtro" style="margin: 4px" onkeyup="wsmanFilter()">
                                </td>
                            </tr>
                        </tbody></table>
                    </div>
                    <br>
                    <div class="us" id="id_wsresults"></div>
                </div>
                <!-- ###END###{WsmanBrowser} -->
                <!-- ###BEGIN###{Terminal} -->
                <div id="p13" style="display:none;min-width:780px">
                    <h1>Terminale seriale su LAN</h1>
                    <br>
                    <div id="id_p13warning1" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showFeaturesDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">La porta di reindirizzamento Intel® AMT o la funzionalità Serial-over-LAN è disabilitata<span id="id_p13warninga">, fai clic qui per abilitarlo.</span></div>
                    </div>
                    <!-- ###BEGIN###{PowerControl} -->
                    <div id="id_p13warning2" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showPowerActionDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">Il computer remoto non è acceso, fare clic qui per emettere un comando di accensione.</div>
                    </div>
                    <!-- ###END###{PowerControl} -->
                    <table cellpadding="0" cellspacing="0" style="width:100%;padding:0px;padding:0px;margin-top:0px">
                        <tbody><tr>
                            <td style="padding-top:2px;padding-bottom:2px;background:#CCC">
                                <div style="float:right; text-align:right">
                                    <input onkeyup="sendTermInputKeys(event)" autocorrect="off" autocapitalize="off" style="opacity:0;width:0;height:0;font-size:1px" onblur="keyInputBlur()">
                                    <span id="id_p13power"></span>&nbsp;
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <div id="termRecordIcon" title="Server is recording this session" style="display:none;float:right;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-right:4px"></div>
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <!-- ###BEGIN###{PowerControl} -->
                                    <input type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Azioni di potere ..." onclick="showPowerActionDlg()" style="margin-right:3px">
                                    <!-- ###END###{PowerControl} -->
                                    <!-- ###BEGIN###{IDER} -->
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_SIDER1" value="SIDER" title="Start server-side remote disk mount operation" onkeypress="return false" onkeydown="return false" onclick="iderServerStart()" style="margin-right:3px">
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_IDER1" value="IDER" title="Inizia l'operazione di montaggio del disco remoto" onkeypress="return false" onkeydown="return false" onclick="iderStart(event)" style="margin-right:3px">
                                    <!-- ###END###{IDER} -->
                                    <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                                    <!-- ###BEGIN###{FileSaver} -->
                                    <input id="idx_terminalCaptureButton" type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Avvia acquisizione" title="Toggle start/stop of terminal capture, when stopping the content of the capture buffer will be saved to a file." onclick="terminalCaptureToggle(event)" style="margin-right:3px">
                                    <!-- ###END###{FileSaver} -->
                                    <!-- ###BEGIN###{TerminalReplay} -->
                                    <!-- <input id="idx_terminalReplayButton" type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Replay Capture" onclick="terminalReplay()" style="margin-right:3px"> -->
                                    <!-- ###END###{TerminalReplay} -->
                                    <!-- ###END###{!Mode-NodeWebkit} -->
                                </div>
                                <div>
                                    &nbsp;<input type="button" id="idx_connectbutton2" value="Collegare" onclick="connectTerminal(event)" disabled="disabled">
                                    &nbsp;<span id="id_termstatus">Disconnected.</span>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td style="background:#000;text-align:center"><pre id="Term"></pre></td>
                        </tr>
                        <tr>
                            <td style="padding-top:2px;padding-bottom:2px;background:#CCC">
                                <div style="float:right;text-align:right">
                                    <input id="id_tcrbutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event);return false" class="bottombutton" value="CR + LF" title="Cambia ciò che invierà il tasto invio" onclick="termToggleCr();Q('id_tcrbutton').blur()">
                                    <!-- ###BEGIN###{TerminalSize} -->
                                    <input id="id_tsizebutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="80x25" title="Attiva / disattiva le dimensioni del terminale" onclick="termToggleSize();Q('id_tsizebutton').blur()">
                                    <!-- ###END###{TerminalSize} -->
                                    <input id="id_tfxkeysbutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event);return false" class="bottombutton" value="Intel (F10 = ESC + [OM)" title="Cambia il tipo di emulazione dei tasti da F1 a F10" onclick="termToggleFx();Q('id_tfxkeysbutton').blur()">
                                    <!-- ###BEGIN###{Terminal-Enumation-All} -->
                                    <input id="id_ttypebutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event);return false" class="bottombutton" value="Ascii esteso" title="Attiva / disattiva il tipo di emulazione terminale" onclick="termToggleType();Q('id_ttypebutton').blur()">&nbsp;
                                    <!-- ###END###{Terminal-Enumation-All} -->
                                </div>
                                <div>
                                    <!-- ###BEGIN###{Mode-NodeWebkit} -->
                                    <input id="id_toolbtncc" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="Ctl-C" onclick="termSendKey(3);Q('id_toolbtncc').blur()">
                                    <input id="id_toolbtncx" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="Ctl-X" onclick="termSendKey(24);Q('id_toolbtncx').blur()">
                                    <input id="id_toolbtnes" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="ESC" onclick="termSendKey(27);Q('id_toolbtnes').blur()">
                                    <input id="id_toolbtnbs" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="Backspace" onclick="termSendKey(8);Q('id_toolbtnbs').blur()">
                                    <!-- ###END###{Mode-NodeWebkit} -->
                                    <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                                    <span id="termkeysspan">
                                        <select style="margin-left:6px" id="termkeys">
                                            <option value="3">Ctrl-C</option>
                                            <option value="24">Ctrl-X</option>
                                            <option value="27">ESC</option>
                                            <option value="8">Backspace</option>
                                            <option value="1001">F1</option>
                                            <option value="1002">F2</option>
                                            <option value="1003">F3</option>
                                            <option value="1004">F4</option>
                                            <option value="1005">F5</option>
                                            <option value="1006">F6</option>
                                            <option value="1007">F7</option>
                                            <option value="1008">F8</option>
                                            <option value="1009">F9</option>
                                            <option value="1010">F10</option>
                                            <option value="1011">F11</option>
                                            <option value="1012">F12</option>
                                        </select>
                                        <input id="TermWD" type="button" value="Spedire" onkeypress="return false" onkeydown="return false" onclick="termSendKeys()">
                                        &nbsp;
                                    </span>
                                    <!-- ###END###{!Mode-NodeWebkit} -->
                                    <input id="id_tpastebutton" type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Incolla" disabled="disabled" onclick="setDialogMode(3,'Paste',3,termPaste)">
                                </div>
                            </td>
                        </tr>
                    </tbody></table>
                </div>
                <!-- ###END###{Terminal} -->
                <!-- ###BEGIN###{Desktop} -->
                <div id="p14" style="display:none;min-width:780px">
                    <div id="id_rdheader"><h1>Desktop remoto</h1><br></div>
                    <div id="id_p14warning1" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showFeaturesDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">La porta di reindirizzamento Intel® AMT o la funzionalità KVM è disabilitata<span id="id_p14warninga">, fai clic qui per abilitarlo.</span></div>
                    </div>
                    <!-- ###BEGIN###{PowerControl} -->
                    <div id="id_p14warning2" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showPowerActionDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">Il computer remoto non è acceso, fare clic qui per emettere un comando di accensione.</div>
                    </div>
                    <!-- ###END###{PowerControl} -->
                    <table cellpadding="0" cellspacing="0" style="width: 100%; padding: 0px; padding: 0px; margin-top: 0px">
                        <tbody><tr>
                            <td style="padding-top: 2px;padding-bottom:2px;background: #CCC">
                                <div style="float:right; text-align:right">
                                    <span id="id_p14power"></span>&nbsp;
                                    <div class="rb" title="Gira a sinistra" onclick="drotate(-1)">↺</div>
                                    <div class="rb" title="Ruota a destra" onclick="drotate(1)">↻</div>
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <div id="deskRecordIcon" title="Server is recording this session" style="display:none;float:right;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-right:4px"></div>
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <input id="idx_deskFullBtn" type="button" title="Attiva / disattiva la modalità a schermo intero" onkeypress="return false" onkeydown="return false" value="Pieno" onclick="deskToggleFull()" style="margin-right:3px">
                                    <!-- ###BEGIN###{DesktopFocus} -->
                                    <input id="idx_deskFocusBtn" type="button" title="Attiva / disattiva la modalità di messa a fuoco, quando attiva viene aggiornata solo la regione intorno al mouse" onkeypress="return false" onkeydown="return false" value="Focus All" onclick="deskToggleFocus()" style="margin-right:3px">
                                    <!-- ###END###{DesktopFocus} -->
                                    <!-- ###BEGIN###{FileSaver} -->
                                    <!-- ###BEGIN###{!DesktopRecorder} -->
                                    <input id="idx_deskSaveBtn" type="button" title="Salva uno screenshot del desktop remoto" onkeypress="return false" onkeydown="return false" value="Salva..." onclick="deskSaveImage()" style="margin-right:3px">
                                    <!-- ###END###{!DesktopRecorder} -->
                                    <!-- ###END###{FileSaver} -->
                                    <input type="button" value="Impostazioni..." title="Modifica le impostazioni del desktop remoto" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" style="margin-right:3px">
                                    <!-- ###BEGIN###{IDER} -->
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_SIDER2" value="SIDER" title="Start server-side remote disk mount operation" onkeypress="return false" onkeydown="return false" onclick="iderServerStart()" style="margin-right:3px">
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_IDER2" value="IDER" title="Inizia l'operazione di montaggio del disco remoto" onkeypress="return false" onkeydown="return false" onclick="iderStart(event)" style="margin-right:3px">
                                    <!-- ###END###{IDER} -->
                                    <!-- ###BEGIN###{PowerControl} -->
                                    <input type="button" title="Cambia lo stato di alimentazione della macchina remota" onkeypress="return false" onkeydown="return false" value="Azioni di potere ..." onclick="showPowerActionDlg()" style="margin-right:3px">
                                    <!-- ###END###{PowerControl} -->
                                </div>
                                <div>
                                    <div id="idx_deskFullBtn2" onclick="deskToggleFull()" style="float:left;cursor:pointer;font-size:15px;display:none">&nbsp;✖</div>
                                    &nbsp;<input type="button" id="idx_connectbutton1" value="Collegare" onclick="connectDesktopButton(event)" onkeypress="return false" onkeydown="return false" disabled="disabled">
                                    &nbsp;<span id="id_deskstatus">Disconnected.</span>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td id="id_DeskParent" style="background:black;text-align:center;position:relative">
                                <!-- ###BEGIN###{DesktopFocus} -->
                                <div id="DeskFocus" style="color:transparent;border:3px dotted rgba(255,0,0,.2);position:absolute;border-radius:5px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></div>
                                <!-- ###END###{DesktopFocus} -->
                                <!-- ###BEGIN###{DesktopInband} -->
                                <canvas id="Desk" width="640" height="400" style="-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" onwheel="dmousewheel(event)" moz-opaque=""></canvas>
                                <!-- ###END###{DesktopInband} -->
                                <!-- ###BEGIN###{!DesktopInband} -->
                                <canvas id="Desk" width="640" height="400" style="-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" moz-opaque=""></canvas>
                                <!-- ###END###{!DesktopInband} -->
                            </td>
                        </tr>
                        <tr>
                            <td style="padding-top:2px;padding-bottom:2px;background:#CCC">
                                <!--
                        <div style="float:right; text-align:right">
                            <select id="specialkeylist" onkeypress="return false"></select>
                            <input id="specialkeylistinput" type="button" onkeypress="return false" class="bottombutton" value="Send" onclick="sendSpecialKey()">&nbsp;
                        </div>
                        -->
                                <!-- ###BEGIN###{DesktopClipboard} -->
                                <input id="id_DeskKvmClipButton" value="appunti" type="button" style="float:right;display:none" onclick="deskClipboard()">
                                <!-- ###END###{DesktopClipboard} -->
                                <!-- ###BEGIN###{FileSaver} -->
                                <!-- ###BEGIN###{DesktopRecorder} -->
                                <div id="id_DeskRecorderTools" style="float:right">
                                    <div id="DeskRecordButton" class="videoIcon" title="Registra la sessione del desktop remoto su file" onclick="deskRecordSession()"></div>
                                    <div id="DeskSaveImageButton" class="cameraIcon" title="Salva uno screenshot del desktop remoto" onclick="deskSaveImage()"></div>
                                </div>
                                <!-- ###END###{DesktopRecorder} -->
                                <!-- ###END###{FileSaver} -->
                                <!-- ###BEGIN###{Desktop-Multi} -->
                                <div id="id_DeskScreenSelector" style="float:right"></div>
                                <!-- ###END###{Desktop-Multi} -->
                                <div>
                                    &nbsp;
                                    <span id="deskkeysspan">
                                        <select style="margin-left:6px" id="deskkeys">
                                            <option value="0">Vincere</option>
                                            <option value="1">Win + Giù</option>
                                            <option value="2">Win + Up</option>
                                            <option value="3">Win + L</option>
                                            <option value="4">Win + M</option>
                                            <option value="20">Win + R</option>
                                            <option value="23">Win + Sinistra</option>
                                            <option value="24">Win + Destra</option>
                                            <option value="5">Maiusc + Win + M</option>
                                            <option value="19">Alt-Tab</option>
                                            <option value="21">Alt-F4</option>
                                            <option value="22">Ctrl-W</option>
                                            <option value="6">F1</option>
                                            <option value="7">F2</option>
                                            <option value="8">F3</option>
                                            <option value="9">F4</option>
                                            <option value="10">F5</option>
                                            <option value="11">F6</option>
                                            <option value="12">F7</option>
                                            <option value="13">F8</option>
                                            <option value="14">F9</option>
                                            <option value="15">F10</option>
                                            <option value="16">F11</option>
                                            <option value="17">F12</option>
                                            <option value="25">Enter</option>
                                            <!-- <option value=18>LS+LA+PrtSc</option> -->
                                        </select>
                                        <input id="DeskWD" type="button" value="Spedire" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()">
                                        &nbsp;
                                    </span>
                                    <input id="id_DeskCAD" type="button" value="Ctrl-Alt-Del" onkeypress="return false" onkeydown="return false" onclick="sendCAD()">&nbsp;
                                    <!-- ###BEGIN###{DesktopType} -->
                                    <input id="id_DeskType" type="button" value="genere" onkeypress="return false" onkeydown="return false" onclick="deskShowTypeDialog()">&nbsp;
                                    <!-- ###END###{DesktopType} -->
                                    <span id="id_DeskSBspan"><input id="id_DeskSB" type="checkbox"> Schermo nero&nbsp;</span>
                                    <span id="id_DeskVOspan"><input id="id_DeskVO" type="checkbox"> Visualizzare solamente&nbsp;</span>
                                </div>
                            </td>
                        </tr>
                    </tbody></table>
                </div>
                <!-- ###END###{Desktop} -->
                <!-- ###BEGIN###{AuditLog} -->
                <div id="p15" style="display:none">
                    <span id="id_TableAuditLog1"></span>
                    <h1>Registro di audizione</h1>
                    <span id="id_TableAuditLog2"></span>
                </div>
                <!-- ###END###{AuditLog} -->
                <!-- ###BEGIN###{Certificates} -->
                <div id="p16" style="display:none">
                    <h1>Impostazioni sicurezza</h1>
                    <span id="id_TableCerts"></span>
                </div>
                <!-- ###END###{Certificates} -->
                <!-- ###BEGIN###{RemoteAccess} -->
                <div id="p17" style="display:none">
                    <h1>Impostazioni Internet</h1>
                    <span id="id_TableRemoteAccess"></span>
                </div>
                <!-- ###END###{RemoteAccess} -->
                <!-- ###BEGIN###{SystemDefense} -->
                <div id="p18" style="display:none">
                    <h1>Difesa del sistema</h1>
                    <span id="id_TableSystemDefense"></span>
                </div>
                <!-- ###END###{SystemDefense} -->
                <!-- ###BEGIN###{AgentPresence} -->
                <div id="p19" style="display:none">
                    <h1>Presenza agente</h1>
                    <span id="id_TableSystemAgentPresence"></span>
                </div>
                <!-- ###END###{AgentPresence} -->
                <!-- ###BEGIN###{Scripting-Editor} -->
                <div id="p20" style="display:none">
                    <h1>Editor di script</h1>
                    <div class="log1" style="padding:5px;border-radius:5px">
                        <div id="EditScriptStatus" style="float:right;font-weight:bold;padding:5px">Fermato</div>
                        <div>
                            <input type="button" value="Visualizza editor" title="Passa alla vista dell'editor della riga di script" id="viewEditorButton" onclick="scriptViewButton(0)">
                            <input type="button" value="Visualizza Builder" title="Passa alla vista dell'editor di blocco" id="viewBuilderButton" onclick="scriptViewButton(1)">
                            <input type="button" value="Nuovo..." title="Cancella l'editor di script" onclick="script_newScriptDlg()">
                            <input type="button" value="Caricare..." title="Carica uno script dal file" onclick="script_runScriptDlg()">
                            <!-- ###BEGIN###{FileSaver} -->
                            <input type="button" value="Salva..." title="Salva uno script in un file" onclick="script_saveScript(event)">
                            <!-- ###END###{FileSaver} -->
                            <input type="button" value="Ricomincia" title="Compilare lo script e prepararsi a eseguirlo dall'inizio" onclick="resetScriptButton()">
                            <input type="button" value="Continua" title="Esegui lo script dal punto di esecuzione corrente" onclick="runScriptButton()">
                            <input type="button" value="Rompere" title="Metti in pausa l'esecuzione dello script" onclick="breakScriptButton()">
                            <input type="button" value="Passo" title="Esegui un passaggio dello script" onclick="stepScriptButton()">
                        </div>
                    </div>
                    <div id="scriptbuilder" style="display:none">
                        <h2>Script Builder</h2>
                        <div style="padding:0;margin:0">
                            <div style="width:250px;height:400px;float:left;padding:0;margin:0;padding-right:3px">
                                <input id="blockfilter" style="width:inherit;height:24px;padding:0;margin:0;border:1px solid gray;margin-bottom:1px" placeholder="Blocchi filtro ..." onkeyup="script_fonfilterchanged()">
                                <div id="blocks" style="width:inherit;height:373px;border:1px solid gray;overflow-y:scroll;padding:0;margin:0"></div>
                            </div>
                            <div id="scriptblocks" style="width:auto;height:400px;padding:0;margin:0;border:1px solid gray;overflow-y:scroll" ondrop="script_fondrop(event, this)" onclick="script_fonclick(event)"></div>
                        </div>
                    </div>
                    <div id="scripteditor">
                        <h2>copione</h2>
                        <textarea id="scriptarea" style="width:100%;height:176px;resize:vertical;margin:0;padding:0;font-family:Arial,Helvetica,sans-serif" spellcheck="false"></textarea>
                        <div style="display:none">
                            <br><h2>Script compilato</h2>
                            <textarea id="compiledarea" style="width:100%;height:16px;resize:vertical;margin:0;padding:0" spellcheck="false"></textarea>
                            <br>
                        </div>
                        <h2>variabili</h2>
                        <div id="variables" style="width:100%;height:200px;resize:vertical;border:1px solid gray;overflow:scroll;margin:0;padding:0;user-select:text;-webkit-user-select:text;-khtml-user-select:text;-moz-user-select:text;-ms-user-select:text"></div>
                    </div>
                    <h2>consolle</h2>
                    <textarea id="console" style="width:100%;height:80px;resize:vertical;margin:0;padding:0;user-select:text;-webkit-user-select:text;-khtml-user-select:text;-moz-user-select:text;-ms-user-select:text" readonly=""></textarea>
                </div>
                <!-- ###END###{Scripting-Editor} -->
                <!-- ###BEGIN###{Storage} -->
                <div id="p21" style="display:none">
                    <h1>Conservazione</h1>
                    <span id="id_TableSystemStorage"></span>
                </div>
                <!-- ###END###{Storage} -->
                <!-- ###BEGIN###{EventSubscriptions} -->
                <div id="p22" style="display:none">
                    <h1>Abbonamenti ad eventi</h1>
                    <span id="id_TableEventSubscriptions"></span>
                </div>
                <!-- ###END###{EventSubscriptions} -->
                <!-- ###BEGIN###{Alarms} -->
                <div id="p23" style="display:none">
                    <h1>Wake Alarms</h1>
                    <span id="id_TableAlarm"></span>
                </div>
                <!-- ###END###{Alarms} -->
                <!-- ###BEGIN###{DesktopInbandFiles} -->
                <div id="p24" style="display:none;position:absolute;top:0px;bottom:0px;left:8px;right:24px">
                    <h1>File</h1><br>
                    <table id="p24toolbar" style="width:100%;position:absolute;top:35px" cellpadding="0" cellspacing="0">
                        <tbody><tr>
                            <td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign="bottom">
                                <div id="p24rightOfButtons" style="float:right;margin-top:3px"></div>
                                <div>
                                    <input type="button" id="p24FolderUp" disabled="disabled" onclick="p24folderup()" value="Su">&nbsp;
                                    <input type="button" id="p24SelectAllButton" disabled="disabled" onclick="p24selectallfile()" value="Seleziona tutto" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24RenameFileButton" disabled="disabled" value="Rinominare" onclick="p24renamefile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24DeleteFileButton" disabled="disabled" value="Elimina" onclick="p24deletefile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24NewFolderButton" disabled="disabled" value="Nuova cartella" onclick="p24createfolder()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24UploadButton" disabled="disabled" value="Caricare" onclick="p24uploadFile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24CutButton" disabled="disabled" value="Taglio" onclick="p24copyFile(1)" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24CopyButton" disabled="disabled" value="copia" onclick="p24copyFile(0)" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24PasteButton" disabled="disabled" value="Incolla" onclick="p24pasteFile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24RefreshButton" disabled="disabled" value="ricaricare" onclick="p24folderup(9999)" onkeypress="return false" onkeydown="return false">&nbsp;
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td style="background-color:#E4E9E7;height:28px">
                                <div style="float:right;margin-right:4px">
                                    <select id="p24sortdropdown" onchange="p24updateFiles()">
                                        <option value="1" selected="selected">Ordina per nome</option>
                                        <option value="2">Ordina per dimensione</option>
                                        <option value="3">Ordinare per data</option>
                                        <option value="4">Scendi per nome</option>
                                        <option value="5">Scendi per dimensione</option>
                                        <option value="6">Scendi per data</option>
                                    </select>
                                </div>
                                <div>&nbsp;&nbsp;<span id="p24currentpath"></span></div>
                            </td>
                        </tr>
                    </tbody></table>
                    <div id="p24filetable" style="width:100%;overflow:auto;-webkit-user-select:none;position:absolute;top:92px;bottom:30px">
                        <div id="p24bigok" style="width:256px;overflow:hidden;position:absolute;top:80px;width:100%;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✓</b></div>
                        <div id="p24bigfail" style="width:256px;overflow:hidden;position:absolute;top:80px;width:100%;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✗</b></div>
                        <span id="p24files"></span>
                    </div>
                    <table id="p24toolbarBottom" style="width:100%;position:absolute;bottom:10px" cellpadding="0" cellspacing="0">
                        <tbody><tr><td style="text-align:left;padding:3px;text-align:center;background-color:#D3D9D6">&nbsp;<span id="p24bottomstatus"></span></td></tr>
                    </tbody></table>
                </div>
                <!-- ###END###{DesktopInbandFiles} -->
            </div>
        </div>
    </div>
    <!-- ###BEGIN###{Mode-MeshCentral2} -->
    <div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial, Helvetica, sans-serif;border-radius:5px;position:fixed;overflow:hidden;top:75px;width:400px;max-height:550px;display:none">
    <!-- ###END###{Mode-MeshCentral2} -->
    <!-- ###BEGIN###{!Mode-MeshCentral2} -->
    <div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial, Helvetica, sans-serif;border-radius:5px;position:fixed;top:160px;width:400px;display:none">
    <!-- ###END###{!Mode-MeshCentral2} -->
        <div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
            <div id="id_dialogclose" style="float:right;padding:1px;margin-right:5px;cursor:pointer;font-size:15px" onclick="setDialogMode()">✖</div>
            <div id="id_dialogtitle" style="padding:5px"></div>
            <div style="width:100%;margin:6px"></div>
        </div>
        <div style="margin-right:16px;margin-left:8px">
            <div id="dialog1" style="margin:auto;text-align:center;margin:3px">
                <div id="id_dialogMessage" style="padding:10px"></div>
            </div>
            <div id="dialog2" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d2username" style="float:right;width:200px" onkeyup="updateAccountDialog()"><div>Nome utente</div></div>
                <div style="height:26px"><input id="d2password1" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="updateAccountDialog()"><div>Parola d'ordine*</div></div>
                <div style="height:26px"><input id="d2password2" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="updateAccountDialog()"><div>conferma password</div></div>
                <div id="id_d2permissions">
                    <div style="height:26px"><select id="d2permission" style="float:right;width:200px"><option value="0">Locale</option><option value="1">Rete</option><option value="2">Qualunque</option></select><div>Autorizzazione</div></div>
                    <div>Autorizzazioni concesse</div>
                    <ul id="id_d2realms" style="list-style-type:none;height:100px;overflow:auto;width:100%;border: 1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0"></ul>
                </div>
                <div style="font-size:10px"><br>* Minimo 8 caratteri con maiuscolo, minuscolo, 0-9 e uno di! @ # $% ^ &amp; * () + -</div>
            </div>
            <!-- ###BEGIN###{Terminal} -->
            <div id="dialog3" style="margin:auto;text-align:center;margin:3px">
                <textarea id="d3pastetextarea" maxlength="4096" style="width:100%;height:200px;resize:none"></textarea>
            </div>
            <!-- ###END###{Terminal} -->
            <!-- ###BEGIN###{Mode-LMS} -->
            <div id="dialog4" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d4username" placeholder="Admin" style="float:right;width:200px" onkeyup="lmsUpdateLoginDialog(event, 1)"><div>Nome utente</div></div>
                <div style="height:26px"><input id="d4password" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="lmsUpdateLoginDialog(event, 2)"><div>Parola d'ordine*</div></div>
                <div style="font-size:10px"><br>* Minimo 8 caratteri con maiuscolo, minuscolo, 0-9 e uno di! @ # $% ^ &amp; * () + -</div>
            </div>
            <!-- ###END###{Mode-LMS} -->
            <!-- ###BEGIN###{ComputerSelector} -->
            <div id="dialog4" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d4name" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Nome amichevole</div></div>
                <div style="height:26px"><input id="d4tags" list="d4devGroups" style="float:right;width:200px" placeholder="Il mio gruppo"><div>Nome del gruppo</div></div>
                <div style="height:26px"><input id="d4hostname" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Nome host</div></div>
                <div style="height:26px"><select id="d4security" style="float:right;width:200px" onchange="updateComputerDialog()"><option value="0">Digest / Nessuno</option><option value="1">Digest / TLS</option><option value="2">Kerberos / Nessuno</option><option value="3">Kerberos / TLS</option></select><div>Auth / Security</div></div>
                <div id="d4digest">
                    <div style="height:26px"><input id="d4username" value="Admin" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Nome utente</div></div>
                    <div style="height:26px"><input id="d4password" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Parola d'ordine*</div></div>
                    <div style="font-size:10px"><br>* Minimo 8 caratteri con maiuscolo, minuscolo, 0-9 e uno di! @ # $% ^ &amp; * () + -</div>
                </div>
                <div id="d4kerb">
                    <div style="height:26px"><input id="d4kerberos" style="float:right;width:200px" onkeyup="updateComputerDialog()" placeholder="computer.domain.com:16992" title="Se questo campo è compilato, questo valore verrà utilizzato per richiedere il token Kerberos anziché host: port."><div>Richiesta di token opzionale *</div></div>
                    <div style="font-size:10px"><br>* Nome host alternativo per la richiesta di token Kerberos</div>
                </div>
                <datalist id="d4devGroups"></datalist>
            </div>
            <!-- ###END###{ComputerSelector} -->
            <div id="dialog5" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="d5actionSelect" style="float:right;width:200px"></select>
                    <div>Azione di potere</div>
                </div>
                <div>
                    <span style="color:red">Avvertimento:</span> Alcune azioni energetiche possono causare la perdita di dati e la disconnessione delle sessioni di reindirizzamento del desktop, del terminale o del disco.
                </div>
            </div>
            <div id="dialog6" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d6ConsentText" style="float:right;width:200px" maxlength="6" onkeyup="consentChanged()" onkeypress="if (event.keyCode == 13) return dialogclose(1); else return numbersOnly(event)"><div>Codice di consenso</div></div>
                <div style="height:26px"><select id="d6Display" onchange="changeConsentDisplay()" style="float:right;width:200px"><option value="0">Display principale</option><option value="1">Display secondario</option><option id="d6ThirdDisplay" value="2" style="display:none">Terzo display</option></select><div>Visualizzazione del consenso</div></div>
            </div>
            <!-- ###BEGIN###{Desktop} -->
            <div id="dialog7" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d7desktopmode" style="float:right;width:200px"></select>
                    <div>Codifica immagine</div>
                </div>
                <div id="d7decimationspan" style="height:26px">
                    <select id="d7decimation" style="float:right;width:200px"><option value="0">Don't set</option><option value="1">Disabilitato</option><option value="2">Automatic</option><option value="3">Abilitato</option></select>
                    <div>Downscaling</div>
                </div>
                <div style="height:80px">
                    <div style="float:right;border:1px solid #666;width:200px;height:80px;overflow-y:scroll;background-color:white">
                        <!-- ###BEGIN###{DesktopFocus} -->
                        <label><input type="checkbox" id="d7showfocus">Mostra strumento di messa a fuoco</label><br>
                        <!-- ###END###{DesktopFocus} -->
                        <label><input type="checkbox" id="d7showcursor">Mostra cursore del mouse locale</label><br>
                        <label><input type="checkbox" id="d7showcad">Mostra Ctrl-Alt-Canc</label><br>
                        <label><input type="checkbox" id="d7limitFrameRate">Frame rate limite</label><br>
                        <label><input type="checkbox" id="d7noMouseRotate">Non ruotare il mouse</label><br>
                        <label><input type="checkbox" id="d7kvmrmw">Reverse Mouse Wheel</label><br>
                    </div>
                    <div>Altre impostazioni</div>
                </div>
                <!-- ###BEGIN###{DesktopInband} -->
                <div id="d7softkvmsettings" style="display:none">
                    <h4 style="width:100%;border-bottom:1px solid gray">Software KVM</h4>
                    <div style="margin:3px 0 3px 0">
                        <select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl">
                            <option value="50">50%</option>
                            <option value="40">40%</option>
                            <option selected="selected" value="30">30%</option>
                            <option value="20">20%</option>
                            <option value="10">10%</option>
                            <option value="5">5%</option>
                            <option value="1">1%</option>
                        </select>
                        <div style="height:20px">Qualità</div>
                    </div>
                    <div style="margin:3px 0 3px 0">
                        <select id="d7bitmapscaling" style="float:right;width:200px;height:20px" dir="rtl">
                            <option selected="selected" value="1024">100%</option>
                            <option value="896">87,5%</option>
                            <option value="768">75%</option>
                            <option value="640">62,5%</option>
                            <option value="512">50%</option>
                            <option value="384">37,5%</option>
                            <option value="256">25%</option>
                            <option value="128">12,5%</option>
                        </select>
                        <div style="height:20px">scalata</div>
                    </div>
                </div>
                <!-- ###END###{DesktopInband} -->
            </div>
            <!-- ###END###{Desktop} -->
            <!-- ###BEGIN###{!Mode-Firmware} -->
            <div id="dialog8" style="display:table;margin:3px">
                <div style="margin:3px 0 3px 0;padding-top:5px">
                    <input id="idx_d8username" value="Admin" style="float:right;width:220px">
                    <div style="height:20px">Nome utente</div>
                </div>
                <div style="margin:3px 0 3px 0">
                    <input id="idx_d8password" type="password" autocomplete="off" style="float:right;width:220px">
                    <div style="height:20px">Parola d'ordine</div>
                </div>
            </div>
            <!-- ###END###{!Mode-Firmware} -->
            <div id="dialog9" style="margin:auto;margin:3px">
                <label style="display:block"><input type="checkbox" id="idx_d9redir">Porta di reindirizzamento</label>
                <label id="idx_d9kvm_div" style="display:block"><input type="checkbox" id="idx_d9kvm">Desktop remoto KVM</label>
                <label style="display:block"><input type="checkbox" id="idx_d9ider">IDE-reindirizzamento<br></label>
                <label style="display:block"><input type="checkbox" id="idx_d9sol">Serial-over-LAN<br></label>
            </div>
            <div id="dialog10" style="margin:auto;margin:3px">
                <label><input type="radio" name="d10" id="idx_d10none" value="0">Non richiesto<br></label>
                <label><input type="radio" name="d10" id="idx_d10kvm" value="1">Richiesto solo per KVM<br></label>
                <label><input type="radio" name="d10" id="idx_d10all" value="4294967295">Sempre richiesto<br></label>
            </div>
            <div id="dialog11" style="margin:auto;margin:3px">
                <div id="id_dialogOptions"></div>
            </div>
            <!-- ###BEGIN###{Wireless} -->
            <div id="dialog12" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="idx_d12name" style="float:right;width:200px" maxlength="32" onkeyup="updateWifiDialog()" title="Massimo 32 caratteri"><div title="Massimo 32 caratteri">Nome del profilo</div></div>
                <div style="height:26px"><input id="idx_d12ssid" style="float:right;width:200px" maxlength="32" onkeyup="updateWifiDialog()" title="Massimo 32 caratteri"><div title="Massimo 32 caratteri">SSID</div></div>
                <div style="height:26px">
                    <select id="idx_d12pri" style="float:right;width:200px" onclick="updateWifiDialog()"></select>
                    <div>Priorità</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d12auth" style="float:right;width:200px" onclick="updateWifiDialog()"></select>
                    <div>Autenticazione</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d12enc" style="float:right;width:200px" onclick="updateWifiDialog()">
                        <option id="id_d12e4" value="4">CCMP-AES</option>
                        <option id="id_d12e3" value="3">TKIP-RC4</option>
                        <!--<option id="id_d12e2" value="2">WEP</option>-->
                        <!--<option id="id_d12e5" value="5">None</option>-->
                    </select>
                    <div>crittografia</div>
                </div>
                <div id="idx_d12pass">
                    <div style="height:26px"><input id="idx_d12password1" type="password" style="float:right;width:200px" maxlength="63" onkeyup="updateWifiDialog()" title="Lunghezza tra 8 e 63 caratteri"><div title="Lunghezza tra 8 e 63 caratteri">Parola d'ordine*</div></div>
                    <div style="height:26px"><input id="idx_d12password2" type="password" style="float:right;width:200px" maxlength="63" onkeyup="updateWifiDialog()" title="Lunghezza tra 8 e 63 caratteri"><div title="Lunghezza tra 8 e 63 caratteri">conferma password</div></div>
                </div>
                <!-- ###BEGIN###{NetAuth} -->
                <div id="idx_d12netauth" style="display:none">
                    <div id="idx_d12protocoldiv" style="height:26px">
                        <select id="idx_d12protocol" style="float:right;width:200px" onchange="updateNetAuth2Dialog(event)">
                            <option value="0" selected="selected">EAP-TLS</option>
                            <option value="1">EAP-TTLS/MSCHAPv2</option>
                            <option value="2">PEAPv0/EAP-MSCHAPv2</option>
                            <option value="3">PEAPv1/EAP-GTC</option>
                            <option value="4">EAP-FAST/MSCHAPv2</option>
                            <option value="5">EAP-FAST/GTC</option>
                            <option value="6">EAP-FAST/TLS</option>
                        </select>
                        <div>Protocollo</div>
                    </div>
                    <div id="idx_d12servernamediv" style="height:26px"><input id="idx_d12servername" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuthDialog()" title="Massimo 32 caratteri"><div title="Massimo 32 caratteri">Server Name</div></div>
                    <div id="idx_d12servernamecomparediv" style="height:26px">
                        <select id="idx_d12servernamecompare" style="float:right;width:200px" onclick="updateNetAuth2Dialog()">
                            <option value="0" selected="selected">Full Name</option>
                            <option value="1">Domain Suffix</option>
                        </select>
                        <div>Server Name Compare</div>
                    </div>
                    <div id="idx_d12domaindiv" style="height:26px"><input id="idx_d12domain" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuth2Dialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Domain</div></div>
                    <div id="idx_d12usernamediv" style="height:26px"><input id="idx_d12username" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuth2Dialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Nome utente</div></div>
                    <div id="idx_d12passworddiv" style="height:26px"><input id="idx_d12password" type="password" style="float:right;width:200px" maxlength="32" onkeyup="updateNetAuth2Dialog()" title="Maximum length is 32 characters"><div title="Maximum length is 32 characters">Parola d'ordine</div></div>
                    <div id="idx_d12roamingidentitydiv" style="height:26px"><input id="idx_d12roamingidentity" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuth2Dialog()" title="Maximum 80 characters"><div title="Maximum 80 characters">Roaming Identity</div></div>
                    <div id="idx_d12pacdiv" style="height:26px"><input id="idx_d12pac" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuth2Dialog()" title="Maximum 256 characters"><div title="Maximum 256 characters">Protected Access Credentials</div></div>
                    <div id="idx_d12pacpassworddiv" style="height:26px"><input id="idx_d12pacpassword" type="password" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuth2Dialog()" title="Maximum length is 256 characters"><div title="Maximum length is 256 characters">PAC Password</div></div>
                    <div id="idx_d12clientcertdiv" style="height:26px">
                        <select id="idx_d12clientcert" style="float:right;width:200px" onclick="updateNetAuth2Dialog()"></select>
                        <div>Client Certificate</div>
                    </div>
                    <div id="idx_d12servercertdiv" style="height:26px">
                        <select id="idx_d12servercert" style="float:right;width:200px" onclick="updateNetAuth2Dialog()"></select>
                        <div>Server Issuer Cert</div>
                    </div>
                    <div id="idx_d12activeins0div" style="height:26px">
                        <select id="idx_d12activeins0" style="float:right;width:200px" onclick="updateNetAuth2Dialog()">
                            <option value="1">Abilitato</option>
                            <option value="0">Disabilitato</option>
                        </select>
                        <div>Active in S0</div>
                    </div>
                </div>
                <!-- ###END###{NetAuth} -->
            </div>
            <!-- ###END###{Wireless} -->
            <!-- ###BEGIN###{USBSetup} -->
            <div id="dialog13" style="margin:auto;margin:3px">
                <label><input type="checkbox" id="d13valid">Record valido<br></label>
                <span id="d13ScrambledRecordSpan"><label><input type="checkbox" id="d13scramble">Record criptato</label><br></span>
            </div>
            <div id="dialog14" style="margin:auto;margin:3px">
                <div style="height:26px">
                    <select id="idx_d14version" style="float:right;width:200px">
                        <option value="1">Versione 1</option>
                        <option value="2">Versione 2</option>
                        <option value="3">Versione 3</option>
                        <option value="4">Versione 4</option>
                    </select>
                    <div>Versione Setup.bin</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d14consume" style="float:right;width:200px">
                        <option value="1">I record non verranno consumati</option>
                        <option value="0">I record verranno consumati</option>
                    </select>
                    <div>Registra il consumo</div>
                </div>
            </div>
            <div id="dialog15" style="margin:auto;margin:3px">
                <input id="d15setupbinfile" type="file" style="width:100%" accept=".bin">
            </div>
            <div id="dialog16" style="margin:auto;margin:3px">
                <div style="height:26px">
                    <select id="d16type" style="float:right;width:260px" onchange="usb_ond16typechange()" onclick="usb_ond16typechange()" onscroll="usb_ond16typechange()" onkeydown="usb_ond16typechange()"></select>
                    <div>Tipo di variabile</div>
                </div>
                <div id="d16genericvalue" style="height:26px">
                    <select id="idx_d16value1" style="float:right;width:260px"></select>
                    <input id="idx_d16value2" style="float:right;width:260px;display:none">
                    <div>Valore variabile</div>
                </div>
                <div id="d16customvalue"></div>
            </div>
            <!-- ###END###{USBSetup} -->
            <!-- ###BEGIN###{ComputerSelector} -->
            <div id="dialog17" style="margin:auto;margin:3px">
                <input id="idx_d17computerlistfile" type="file" style="width:100%" accept=".json, .csv">
            </div>
            <div id="dialog18" style="margin:auto;margin:3px">
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <input id="idx_d18computerfilename" style="width:100%" value="computerlist.json">
                <!-- ###END###{!Mode-NodeWebkit} -->
                <!-- ###BEGIN###{Mode-NodeWebkit} -->
                <!-- <input id="idx_d18computersavefile" type="file" nwsaveas="computerlist.json" accept=".json"> -->
                <div style="text-align:left;height:26px;padding-top:6px">
                    <label><input id="d18usepassword" type="checkbox" style="float:left" onchange="saveComputerListUpdate()"><div>Usa la crittografia. Il file conterrà le credenziali Intel® AMT, il salvataggio tramite password può aiutare a proteggere questi dati.</div></label>
                </div>
                <div id="d18showpassword" style="display:none;padding-top:16px">
                    <div style="height:26px"><input id="d18password1" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="saveComputerListUpdate()"><div>Parola d'ordine*</div></div>
                    <div style="height:26px"><input id="d18password2" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="saveComputerListUpdate()"><div>conferma password</div></div>
                    <div style="font-size:10px"><br>* Minimo 8 caratteri con maiuscolo, minuscolo, 0-9 e uno di! @ # $% ^ &amp; * () + -</div>
                </div>
                <!-- ###END###{Mode-NodeWebkit} -->
            </div>
            <!-- ###END###{ComputerSelector} -->
            <!-- ###BEGIN###{FileSaver} -->
            <div id="dialog19" style="margin:auto;margin:3px">
                Ciò salverà l'intero stato di Intel® AMT per questa macchina in un file. Le password non verranno salvate, ma potrebbero essere inclusi alcuni dati sensibili.<br><br>
                <input id="idx_d19savestatefilename" style="width:100%" value="amtstate.json">
            </div>
            <!-- ###END###{FileSaver} -->
            <!-- ###BEGIN###{NetworkSettings} -->
            <div id="dialog20" style="margin:auto;margin:3px">
                <input type="radio" name="d20" id="d20a" value="0">Disabilitato<br>
                <input type="radio" name="d20" id="d20b" value="1">Risposta ICMP<br>
                <input type="radio" name="d20" id="d20c" value="2">Risposta RMCP<br>
                <input type="radio" name="d20" id="d20d" value="3">Risposta ICMP e RMCP<br><br>
            </div>
            <div id="dialog21" style="margin:auto;margin:3px">
                <div id="id_d21ipaddrsync">
                    <label><input type="checkbox" name="d21" id="d21ipsync" onclick="updateIPSetupDlg()">Sincronizzazione dell'indirizzo IP del sistema operativo</label><br>
                </div>
                <label><input type="radio" name="d21" id="d21o0" onclick="updateIPSetupDlg()"><span id="d21l0"></span></label><br>
                <label><input type="radio" name="d21" id="d21o1" onclick="updateIPSetupDlg()"><span id="d21l1"></span></label><br>
                <div id="id_d21manualdiv">
                    <label><input type="radio" name="d21" id="d21o2" onclick="updateIPSetupDlg()"><span id="d21l2"></span></label><br><br>
                    <div style="margin-left:20px">
                        <div style="height:26px"><input id="idx_d21address" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>indirizzo IP</div></div>
                        <div style="height:26px" id="id_d21subnetdiv"><input id="idx_d21subnet" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>Contrassegno di sottorete</div></div>
                        <div style="height:26px"><input id="idx_d21gateway" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>porta</div></div>
                        <div style="height:26px"><input id="idx_d21dns1" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>DNS primario</div></div>
                        <div style="height:26px"><input id="idx_d21dns2" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>DNS alternativo</div></div>
                    </div>
                </div>
            </div>
            <div id="dialog23" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d23ddns" style="float:right;width:200px" onchange="showEditDnsDlgChange()">
                        <option value="0">Disabilitato</option>
                        <option value="1">Disabilitato, aggiornamento DHCP</option>
                        <option value="2">Abilitato</option>
                    </select>
                    <div>Client DNS dinamico</div>
                </div>
                <div style="height:26px"><input id="idx_d23interval" style="float:right;width:200px"><div>Intervallo di aggiornamento (minuti)</div></div>
                <div style="height:26px"><input id="idx_d23ttl" style="float:right;width:200px"><div>TTL (secondi)</div></div>
                <div style="font-size:10px"><br>L'intervallo di defaut è di 1440 minuti, il TTL predefinito è di 900 secondi.</div>
            </div>
            <!-- ###END###{NetworkSettings} -->
            <!-- ###BEGIN###{PowerControl-Advanced} -->
            <div id="dialog24" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d24Command" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="2">Accendere</option>
                        <option value="10">Ripristina</option>
                        <option value="5">Ciclo di alimentazione</option>
                        <option value="8">Spegnere</option>
                        <option id="d24p500" value="500">OS Wake from Standby</option>
                        <option id="d24p501" value="501">Risparmio energetico del sistema operativo</option>
                        <option value="999">Imposta le opzioni di avvio</option>
                    </select>
                    <div>Comando remoto</div>
                </div>
                <div style="height:80px">
                    <div id="idx_d24bootoptions" style="float:right;border:1px solid #666;width:200px;height:72px;overflow-y:scroll;background-color:white">
                        <div id="d24dBiosPause"><label><input type="checkbox" id="d24BiosPause" onchange="showAdvPowerDlgChange()">Pausa BIOS</label><br></div>
                        <div id="d24dBiosSecureBoot"><label><input type="checkbox" id="d24BiosSecureBoot" onchange="showAdvPowerDlgChange()">Applica avvio sicuro</label><br></div>
                        <div id="d24dBiosSetup"><label><input type="checkbox" id="d24BiosSetup" onchange="showAdvPowerDlgChange()">Impostazioni del BIOS</label><br></div>
                        <div id="d24dForceProgressEvents"><label><input type="checkbox" id="d24ForceProgressEvents" onchange="showAdvPowerDlgChange()">Forza eventi di avanzamento</label><br></div>
                        <div id="d24dLockPowerButton"><label><input type="checkbox" id="d24LockPowerButton" onchange="showAdvPowerDlgChange()">Blocca il pulsante di accensione</label><br></div>
                        <div id="d24dLockResetButton"><label><input type="checkbox" id="d24LockResetButton" onchange="showAdvPowerDlgChange()">Pulsante di reset del blocco</label><br></div>
                        <div id="d24dLockSleepButton"><label><input type="checkbox" id="d24LockSleepButton" onchange="showAdvPowerDlgChange()">Pulsante di blocco del sonno</label><br></div>
                        <div id="d24dLockKeyboard"><label><input type="checkbox" id="d24LockKeyboard" onchange="showAdvPowerDlgChange()">Blocca tastiera</label><br></div>
                        <div id="d24dUserPasswordBypass"><label><input type="checkbox" id="d24UserPasswordBypass" onchange="showAdvPowerDlgChange()">Bypass password BIOS</label><br></div>
                        <div id="d24dReflashBios"><label><input type="checkbox" id="d24ReflashBios" onchange="showAdvPowerDlgChange()">BIOS Reflash</label><br></div>
                        <div id="d24dSafeMode"><label><input type="checkbox" id="d24SafeMode" onchange="showAdvPowerDlgChange()">Modalità sicura</label><br></div>
                        <div id="d24dUseIDER"><label><input type="checkbox" id="d24UseIDER" onchange="showAdvPowerDlgChange()">Usa IDER</label><br></div>
                        <div id="d24dSerialOverLan"><label><input type="checkbox" id="d24SerialOverLan" onchange="showAdvPowerDlgChange()">Serial-over-LAN</label><br></div>
                        <div id="d24dSecureErase"><label><input type="checkbox" id="d24SecureErase" onchange="showAdvPowerDlgChange()">Intel® Remote Secure Erase</label><br></div>
                        <div id="d24dPlatformErase"><label><input type="checkbox" id="d24PlatformErase" onchange="showAdvPowerDlgChange()">Remote Platform Erase</label><br></div>
                        <div id="d24dFirmwareReset"><label><input type="checkbox" id="d24FirmwareReset" onchange="showAdvPowerDlgChange()">Clear Intel® ME Settings</label><br></div>
                    </div>
                    <div>Impostazioni di avvio</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d24ForceBootDevice" style="float:right;width:200px" onchange="showAdvPowerDlgChange()"></select>
                    <div>Boot Source</div>
                </div>
                <div id="idx_d24bootSource" style="height:26px">
                    <select id="idx_d24BootMediaIndex" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="0">Nessuna</option>
                        <option value="1">Indice 1</option>
                        <option value="2">Indice 2</option>
                        <option value="3">Indice 3</option>
                        <option value="3">Indice 4</option>
                    </select>
                    <div>Boot Media</div>
                </div>
                <!-- ###BEGIN###{PowerControl-OneClick} -->
                <div id="idx_d24customBootSource" style="height:26px;display:none">
                    <select id="idx_d24customBootMediaIndex" onchange="showAdvPowerDlgChange()" style="float:right;width:200px"></select>
                    <div>Boot Media</div>
                </div>
                <div id="idx_d24diskImage" style="height:26px">
                    <input id="idx_d24ocrBootFile" type="file" onchange="showAdvPowerDlgChange()" style="float:right;width:200px" accept=".iso">                    
                    <div>Boot Image</div>
                </div>
                <div id="idx_d24diskImageUrl" style="height:26px">
                    <input id="idx_d24ocrBootUrl" type="text" onchange="showAdvPowerDlgChange()" onkeyup="showAdvPowerDlgChange()" placeholder="https://" style="float:right;width:200px">
                    <div>Boot URL</div>
                </div>
                <div id="idx_d24diskImageHttpTimeout" style="height:26px">
                    <input id="idx_d24ocrBootHttpBootTimeout" type="text" onchange="showAdvPowerDlgChange()" onkeyup="showAdvPowerDlgChange()" value="0" style="float:right;width:200px">
                    <div>Timeout (Seconds)</div>
                </div>
                <!-- ###END###{PowerControl-OneClick} -->
                <div style="height:26px" id="idd_d24IDERBootDevice">
                    <select id="idx_d24IDERBootDevice" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="0">Avvio da floppy</option>
                        <option value="1">Avvia su CD-ROM</option>
                    </select>
                    <div>Dispositivo di avvio IDER</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d24Verbocity" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="0">Default del sistema</option>
                        <option id="idx_d24Verbocity1" value="1">Silenzioso</option>
                        <option id="idx_d24Verbocity2" value="2">verboso</option>
                        <option id="idx_d24Verbocity3" value="3">Schermo nero</option>
                    </select>
                    <div>Verbocity</div>
                </div>
                <div style="height:26px" id="idd_d24RSEPass">
                    <div style="float:right;width:200px"><input type="password" id="d24rsepass" maxlength="32" style="float:right;width:100%"></div>
                    <div>Password RSE</div>
                </div>
                <!-- ###BEGIN###{Mode-NodeWebkit} -->
                <div id="idd_d24RSEPassTlsWarn"><div style="color:red"><b>AVVERTIMENTO:</b> TLS non viene utilizzato, la password verrà inviata in chiaro.</div></div>
                <!-- ###END###{Mode-NodeWebkit} -->
            </div>
            <!-- ###END###{PowerControl-Advanced} -->
            <!-- ###BEGIN###{Alarms} -->
            <div id="dialog25" style="margin:auto;margin:3px">
                <div style="text-align:left">
                    <div style="height:26px;margin-top:4px"><input id="d25alarm_name" style="float:right;width:180px" maxlength="32" onkeyup="alertDialogUpdate()"><div style="padding-top:4px">Nome dell'allarme</div></div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right">
                            <input id="d25alarm_sdate" style="width:180px" maxlength="10" onkeyup="alertDialogUpdate()" onkeypress="return numbersOnly(event,45)">
                        </div>
                        <div style="padding-top:4px">Data di sveglia (anno-mese-giorno)</div>
                    </div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right">
                            <input id="d25alarm_stime" style="width:180px" maxlength="10" onkeyup="alertDialogUpdate()" onkeypress="return numbersOnly(event,58)">
                        </div>
                        <div style="padding-top:4px">Tempo di sveglia (ora: min: sec)</div>
                    </div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right">
                            <input id="d25alarm_interval" style="width:180px" maxlength="10" onkeyup="alertDialogUpdate()" onkeypress="return numbersOnly(event,45)">
                        </div>
                        <div style="padding-top:4px">Intervallo (giorni-ore-min)</div>
                    </div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right;width:180px">
                            <select id="d25alarm_doc" style="width:100%" onchange="showAdvPowerDlgChange()">
                                <option value="0">Mantieni l'allarme</option>
                                <option value="1">Elimina al completamento</option>
                            </select>
                        </div>
                        <div style="padding-top:4px">Dopo la veglia</div>
                    </div>
                </div>
            </div>
            <!-- ###END###{Alarms} -->
            <div id="dialog26" style="margin:auto;margin:3px">
                <div id="d26rpediv">
                    <div>Remote Platform Erase (RPE)</div>
                    <label><input type="radio" name="d26b" id="idx_d26rpe1" value="2">Abilitato<br></label>
                    <label><input type="radio" name="d26b" id="idx_d26rpe0" value="0">Disabilitato<br></label>
                    <hr>
                </div>
                <div>One One Click Recovery (OCR)</div>
                <label><input type="radio" name="d26a" id="idx_d26ocr1" value="1">Abilitato<br></label>
                <label><input type="radio" name="d26a" id="idx_d26ocr0" value="0">Disabilitato<br></label>
            </div>
            <!-- ###BEGIN###{NetAuth} -->
            <div id="dialog27" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d27enabled" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0">Disabilitato</option>
                        <option value="1">Abilitato</option>
                    </select>
                    <div>Abilitato</div>
                </div>
                <div id="idx_d27protocoldiv" style="height:26px">
                    <select id="idx_d27protocol" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0" selected="selected">EAP-TLS</option>
                        <option value="1">EAP-TTLS/MSCHAPv2</option>
                        <option value="2">PEAPv0/EAP-MSCHAPv2</option>
                        <option value="3">PEAPv1/EAP-GTC</option>
                        <option value="4">EAP-FAST/MSCHAPv2</option>
                        <option value="5">EAP-FAST/GTC</option>
                        <option value="6">EAP-FAST/TLS</option>
                    </select>
                    <div>Protocollo</div>
                </div>
                <div id="idx_d27servernamediv" style="height:26px"><input id="idx_d27servername" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuthDialog()" title="Massimo 32 caratteri"><div title="Massimo 32 caratteri">Server Name</div></div>
                <div id="idx_d27servernamecomparediv" style="height:26px">
                    <select id="idx_d27servernamecompare" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0" selected="selected">Full Name</option>
                        <option value="1">Domain Suffix</option>
                    </select>
                    <div>Server Name Compare</div>
                </div>
                <div id="idx_d27domaindiv" style="height:26px"><input id="idx_d27domain" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuthDialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Domain</div></div>
                <div id="idx_d27usernamediv" style="height:26px"><input id="idx_d27username" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuthDialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Nome utente</div></div>
                <div id="idx_d27passworddiv" style="height:26px"><input id="idx_d27password" type="password" style="float:right;width:200px" maxlength="32" onkeyup="updateNetAuthDialog()" title="Maximum length is 32 characters"><div title="Maximum length is 32 characters">Parola d'ordine</div></div>
                <div id="idx_d27roamingidentitydiv" style="height:26px"><input id="idx_d27roamingidentity" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuthDialog()" title="Maximum 80 characters"><div title="Maximum 80 characters">Roaming Identity</div></div>
                <div id="idx_d27pacdiv" style="height:26px"><input id="idx_d27pac" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuthDialog()" title="Maximum 256 characters"><div title="Maximum 256 characters">Protected Access Credentials</div></div>
                <div id="idx_d27pacpassworddiv" style="height:26px"><input id="idx_d27pacpassword" type="password" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuthDialog()" title="Maximum length is 256 characters"><div title="Maximum length is 256 characters">PAC Password</div></div>
                <div id="idx_d27clientcertdiv" style="height:26px">
                    <select id="idx_d27clientcert" style="float:right;width:200px" onclick="updateNetAuthDialog()"></select>
                    <div>Client Certificate</div>
                </div>
                <div id="idx_d27servercertdiv" style="height:26px">
                    <select id="idx_d27servercert" style="float:right;width:200px" onclick="updateNetAuthDialog()"></select>
                    <div>Server Issuer Cert</div>
                </div>
                <div id="idx_d27activeins0div" style="height:26px">
                    <select id="idx_d27activeins0" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0">Abilitato</option>
                        <option value="1">Disabilitato</option>
                    </select>
                    <div>Active in S0</div>
                </div>
                <div id="idx_d27pxetimeoutdiv" style="height:26px"><input id="idx_d27pxetimeout" style="float:right;width:200px" onkeyup="updateNetAuthDialog()"><div>PXE Timeout</div></div>
            </div>
            <!-- ###END###{NetAuth} -->
        </div>
        <div style="padding:10px;margin-bottom:4px">
            <input id="idx_dlgCancelButton" type="button" value="Annulla" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
            <input id="idx_dlgOkButton" type="button" value="ok" style="float:right;width:80px" onclick="dialogclose(1)">
            <div style="height:25px"><input id="idx_dlgDeleteButton" type="button" value="Elimina" style="width:80px;display:none" onclick="dialogclose(2)"></div>
        </div>
    </div>
    <!-- ###BEGIN###{ContextMenus} -->
    <div id="contextMenu" class="contextMenu" style="display:none"></div>
    <!-- ###END###{ContextMenus} -->
    <!-- ###BEGIN###{Mode-NodeWebkit} -->
    <!-- ###END###{Mode-NodeWebkit} -->
    <!-- ###BEGIN###{PowerControl} -->
    <!-- ###END###{PowerControl} -->
        <script type="text/javascript">
        // ###BEGIN###{!Look-BrandedCommander}
        var version = '0.9.6';
        // ###END###{!Look-BrandedCommander}
        // ###BEGIN###{Look-BrandedCommander}
        var version = '1.2.0';
        // ###END###{Look-BrandedCommander}
        var urlvars = {};
        var amtstack;
        var wsstack = null;
// ###BEGIN###{WsmanBrowser}
        var AllWsman = 'AMT_8021xCredentialContext,AMT_8021XProfile,AMT_ActiveFilterStatistics,AMT_AgentPresenceCapabilities,AMT_AgentPresenceInterfacePolicy,AMT_AgentPresenceService,AMT_AgentPresenceWatchdog,AMT_AgentPresenceWatchdogAction,AMT_AlarmClockService,IPS_AlarmClockOccurrence,AMT_AssetTable,AMT_AssetTableService,AMT_AuditLog,AMT_AuditPolicyRule,AMT_AuthorizationService,AMT_BootCapabilities,AMT_BootSettingData,AMT_ComplexFilterEntryBase,AMT_CRL,AMT_CryptographicCapabilities,AMT_EACCredentialContext,AMT_EndpointAccessControlService,AMT_EnvironmentDetectionInterfacePolicy,AMT_EnvironmentDetectionSettingData,AMT_EthernetPortSettings,AMT_EventLogEntry,AMT_EventManagerService,AMT_EventSubscriber,AMT_FilterEntryBase,AMT_FilterInSystemDefensePolicy,AMT_GeneralSettings,AMT_GeneralSystemDefenseCapabilities,AMT_Hdr8021Filter,AMT_HeuristicPacketFilterInterfacePolicy,AMT_HeuristicPacketFilterSettings,AMT_HeuristicPacketFilterStatistics,AMT_InterfacePolicy,AMT_IPHeadersFilter,AMT_KerberosSettingData,AMT_ManagementPresenceRemoteSAP,AMT_MessageLog,AMT_MPSUsernamePassword,AMT_NetworkFilter,AMT_NetworkPortDefaultSystemDefensePolicy,AMT_NetworkPortSystemDefenseCapabilities,AMT_NetworkPortSystemDefensePolicy,AMT_PCIDevice,AMT_PETCapabilities,AMT_PETFilterForTarget,AMT_PETFilterSetting,AMT_ProvisioningCertificateHash,AMT_PublicKeyCertificate,AMT_PublicKeyManagementCapabilities,AMT_PublicKeyManagementService,AMT_PublicPrivateKeyPair,AMT_RedirectionService,AMT_RemoteAccessCapabilities,AMT_RemoteAccessCredentialContext,AMT_RemoteAccessPolicyAppliesToMPS,AMT_RemoteAccessPolicyRule,AMT_RemoteAccessService,AMT_SetupAndConfigurationService,AMT_SNMPEventSubscriber,AMT_StateTransitionCondition,AMT_SystemDefensePolicy,AMT_SystemDefensePolicyInService,AMT_SystemDefenseService,AMT_SystemPowerScheme,AMT_ThirdPartyDataStorageAdministrationService,AMT_ThirdPartyDataStorageService,AMT_TimeSynchronizationService,AMT_TLSCredentialContext,AMT_TLSProtocolEndpoint,AMT_TLSProtocolEndpointCollection,AMT_TLSSettingData,AMT_TrapTargetForService,AMT_UserInitiatedConnectionService,AMT_WebUIService,AMT_WiFiPortConfigurationService,CIM_AbstractIndicationSubscription,CIM_Account,CIM_AccountManagementCapabilities,CIM_AccountManagementService,CIM_AccountOnSystem,CIM_AdminDomain,CIM_AlertIndication,CIM_AssignedIdentity,CIM_AssociatedPowerManagementService,CIM_AuthenticationService,CIM_AuthorizationService,CIM_Battery,CIM_BIOSElement,CIM_BIOSFeature,CIM_BIOSFeatureBIOSElements,CIM_BootConfigSetting,CIM_BootService,CIM_BootSettingData,CIM_BootSourceSetting,CIM_Capabilities,CIM_Card,CIM_Chassis,CIM_Chip,CIM_Collection,CIM_Component,CIM_ComputerSystem,CIM_ComputerSystemPackage,CIM_ConcreteComponent,CIM_ConcreteDependency,CIM_Controller,CIM_CoolingDevice,CIM_Credential,CIM_CredentialContext,CIM_CredentialManagementService,CIM_Dependency,CIM_DeviceSAPImplementation,CIM_ElementCapabilities,CIM_ElementConformsToProfile,CIM_ElementLocation,CIM_ElementSettingData,CIM_ElementSoftwareIdentity,CIM_ElementStatisticalData,CIM_EnabledLogicalElement,CIM_EnabledLogicalElementCapabilities,CIM_EthernetPort,CIM_Fan,CIM_FilterCollection,CIM_FilterCollectionSubscription,CIM_HostedAccessPoint,CIM_HostedDependency,CIM_HostedService,CIM_Identity,CIM_IEEE8021xCapabilities,CIM_IEEE8021xSettings,CIM_Indication,CIM_IndicationService,CIM_InstalledSoftwareIdentity,CIM_KVMRedirectionSAP,CIM_LANEndpoint,CIM_ListenerDestination,CIM_ListenerDestinationWSManagement,CIM_Location,CIM_Log,CIM_LogEntry,CIM_LogicalDevice,CIM_LogicalElement,CIM_LogicalPort,CIM_LogicalPortCapabilities,CIM_LogManagesRecord,CIM_ManagedCredential,CIM_ManagedElement,CIM_ManagedSystemElement,CIM_MediaAccessDevice,CIM_MemberOfCollection,CIM_Memory,CIM_MessageLog,CIM_NetworkPort,CIM_NetworkPortCapabilities,CIM_NetworkPortConfigurationService,CIM_OrderedComponent,CIM_OwningCollectionElement,CIM_OwningJobElement,CIM_PCIController,CIM_PhysicalComponent,CIM_PhysicalElement,CIM_PhysicalElementLocation,CIM_PhysicalFrame,CIM_PhysicalMemory,CIM_PhysicalPackage,CIM_Policy,CIM_PolicyAction,CIM_PolicyCondition,CIM_PolicyInSystem,CIM_PolicyRule,CIM_PolicyRuleInSystem,CIM_PolicySet,CIM_PolicySetAppliesToElement,CIM_PolicySetInSystem,CIM_PowerManagementCapabilities,CIM_PowerManagementService,CIM_PowerSupply,CIM_Privilege,CIM_PrivilegeManagementCapabilities,CIM_PrivilegeManagementService,CIM_ProcessIndication,CIM_Processor,CIM_ProtocolEndpoint,CIM_ProvidesServiceToElement,CIM_Realizes,CIM_RecordForLog,CIM_RecordLog,CIM_RedirectionService,CIM_ReferencedProfile,CIM_RegisteredProfile,CIM_RemoteAccessAvailableToElement,CIM_RemoteIdentity,CIM_RemotePort,CIM_RemoteServiceAccessPoint,CIM_Role,CIM_RoleBasedAuthorizationService,CIM_RoleBasedManagementCapabilities,CIM_RoleLimitedToTarget,CIM_SAPAvailableForElement,CIM_SecurityService,CIM_Sensor,CIM_Service,CIM_ServiceAccessBySAP,CIM_ServiceAccessPoint,CIM_ServiceAffectsElement,CIM_ServiceAvailableToElement,CIM_ServiceSAPDependency,CIM_ServiceServiceDependency,CIM_SettingData,CIM_SharedCredential,CIM_SoftwareElement,CIM_SoftwareFeature,CIM_SoftwareFeatureSoftwareElements,CIM_SoftwareIdentity,CIM_StatisticalData,CIM_StorageExtent,CIM_System,CIM_SystemBIOS,CIM_SystemComponent,CIM_SystemDevice,CIM_SystemPackaging,CIM_UseOfLog,CIM_Watchdog,CIM_WiFiEndpoint,CIM_WiFiEndpointCapabilities,CIM_WiFiEndpointSettings,CIM_WiFiPort,CIM_WiFiPortCapabilities,IPS_AdminProvisioningRecord,IPS_ClientProvisioningRecord,IPS_HostBasedSetupService,IPS_HostIPSettings,IPS_HTTPProxyService,IPS_HTTPProxyAccessPoint,IPS_IderSessionUsingPort,IPS_IPv6PortSettings,IPS_KVMRedirectionSettingData,IPS_KvmSessionUsingPort,IPS_ManualProvisioningRecord,IPS_OptInService,IPS_PowerManagementService,IPS_ProvisioningAuditRecord,IPS_ProvisioningRecordLog,IPS_RasSessionUsingPort,IPS_ScreenConfigurationService,IPS_ScreenSettingData,IPS_SecIOService,IPS_SessionUsingPort,IPS_SolSessionUsingPort,IPS_TLSProvisioningRecord,IPS_WatchDogAction'.split(',');
// ###END###{WsmanBrowser}
        var disconnecturl = null;
// ###BEGIN###{Terminal}
        var terminal;
// ###END###{Terminal}
        var currentView = 0;
        var LoadingHtml = '<div style=text-align:center;padding-top:20px>' + "Caricamento in corso..." + '<div>';
        var amtversion = 0;
        var amtversionmin = 0;
        var amtFirstPull = 0; // Bitmask, Set this when the first pull request is made on a device: 1 = HardwareInfo, 2 = WirelessInfo, 4 = SystemDefense, 8 = Storage, 16 = EventLog, 32 = AuditLog, 64 = ExtraInfo, 128 = 802.1x
// ###BEGIN###{NetworkSettings}
        var amtwirelessif = -1; // Set to the interface index for the wireless interface, -1 if no wireless.
// ###END###{NetworkSettings}
// ###BEGIN###{Desktop}
        var desktop;
        var desktopsettings = { encflags: 1, showfocus: false, showmouse: true, showcad: true, limitFrameRate: false, noMouseRotate: false, decimationMode: 2 };
// ###END###{Desktop}
// ###BEGIN###{Mode-MeshCentral2}
        var currentMeshNode = null;
// ###END###{Mode-MeshCentral2}
        var webcompilerfeatures = [/*###WEBCOMPILERFEATURES###*/];
        var StatusStrs = ["Disconnected", "Connessione in corso ...", "Impostare...", "Collegato"];
// ###BEGIN###{Scripting}
        var scriptstate;
// ###END###{Scripting}
// ###BEGIN###{USBSetup}
        var setupbin;
        var selectedRecord = 0;
        var selectedVariable = 0;
// ###END###{USBSetup}
// ###BEGIN###{!Mode-MeshCentral2}
        var amtPowerPollTimer = null;
// ###END###{!Mode-MeshCentral2}
// ###BEGIN###{Mode-LMS}
        var lms = null;
        // ###END###{Mode-LMS}
        // ###BEGIN###{ComputerSelector-Local}
            // ###BEGIN###{Mode-NodeWebkit}
            var kerberos;
            try { kerberos = require('krb-ticket'); } catch (e) { console.log("Impossibile impostare Kerberos"); }
            if (!kerberos || kerberos.initialize() != 0) { kerberos = null; }
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            var kerberos = null;
            // ###END###{!Mode-NodeWebkit}
            var filterFocus = false;
        // ###END###{ComputerSelector-Local}
        var t, t2, rsepass = null; // Global temporary variable
        // ###BEGIN###{MeshServerConnect}
        var meshCentralServer = null;
        // ###END###{MeshServerConnect}
        // ###BEGIN###{PowerControl-Advanced}
        // ###BEGIN###{PowerControl-OneClick}
        var webserver = null;
        // ###END###{PowerControl-OneClick}
        // ###END###{PowerControl-Advanced}
        // ###BEGIN###{DesktopClipboard}
        var xxKvmClipEnc = null;
        var xxKvmClipVal = null;
        // ###END###{DesktopClipboard}

        function startup() {
            // This is a bit freeky, but all HTML input elements are just going to be accessible directly.
            var allelements = document.getElementsByTagName('input');
            for (t = 0; t < allelements.length; t++) { if (allelements[t].id) { window[allelements[t].id] = allelements[t]; } }

            // ###BEGIN###{!Mode-NodeWebkit}
            urlvars = getUrlVars();
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}

            // Move things around to make space for the left-side toolbar
            QS('id_computerSelector').left = '52px';
            QS('id_computerListParent').left = '52px';
            QS('id_certManagerPanel').left = '52px';
            QS('id_certManagerPanel2').left = '52px';
            QS('id_usbSetupPanel').left = '52px';
            QS('id_usbSetupPanel2').left = '52px';
            // ###BEGIN###{SessionRecording}
            QS('id_sessionPlayerPanel').left = '52px';
            // ###END###{SessionRecording}

            // Parse the runtime arguments
            urlvars = getUrlVars();
            var argv = require('nw.gui').App.argv;
            for (var i in argv) {
                if (argv[i].substring(0,1) == '-') {
                    var j = argv[i].indexOf(':');
                    if (j == -1) {
                        urlvars[argv[i].substring(1)] = 1;
                    } else {
                        urlvars[argv[i].substring(1, j)] = argv[i].substring(j + 1);
                    }
                }
            }

            // If we are in NodeWebkit, check if we need to start a output log.
            if (urlvars.logfile && (typeof urlvars.logfile == 'string')) {
                g_logFile = require('fs').createWriteStream(urlvars.logfile, { flags: 'a' }); // Or 'w' to truncate the file every time the process starts.
                g_logStdout = process.stdout;
                console.logEx = console.log;
                console.log = function () {
                    if (arguments.length == 1) console.logEx(arguments[0]);
                    if (arguments.length == 2) console.logEx(arguments[0], arguments[1]);
                    if (arguments.length == 3) console.logEx(arguments[0], arguments[1], arguments[2]);
                    if (arguments.length == 4) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3]);
                    if (arguments.length == 5) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
                    if (arguments.length == 6) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
                    if (arguments.length == 7) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
                    if (arguments.length == 8) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
                    g_logFile.write(require('util').format.apply(null, arguments) + '\r\n');
                    //g_logStdout.write(require('util').format.apply(null, arguments) + '\r\n'); //console.errorEx(arguments);
                }
                console.errorEx = console.error;
                console.error = console.log;
                console.log('--- LOG START: ' + new Date() + ' ---');
            }

            // If we are in NodeWebkit, check if we need to display the console window
            if (urlvars['debug'] == 1) { require('nw.gui').Window.get().showDevTools(); }

            // Prepend 'script' and 'list' with working directory if set and ':' is not in the string. This covers the case where self-extracting Commander has working directory set incorrectly.
            if (urlvars['script'] && (urlvars['script'].indexOf(':') < 0)) { urlvars['script'] = require('path').dirname(process.execPath) + '\\' + urlvars['script']; }
            if (urlvars['list'] && (urlvars['list'].indexOf(':') < 0)) { urlvars['list'] = require('path').dirname(process.execPath) + '\\' + urlvars['list']; }

            // Setup the TLS security mode
            try {
                NW_TlsSecurityMode = parseInt(localStorage.getItem('TlsSecurityMode') ? localStorage.getItem('TlsSecurityMode') : '1');
                NW_SkipTlsHostnameCheck = parseInt(localStorage.getItem('SkipTlsHostnameCheck') ? localStorage.getItem('SkipTlsHostnameCheck') : '0');
            } catch (ex) {
                NW_TlsSecurityMode = '1';
                NW_SkipTlsHostnameCheck = '0';
            }
            if (urlvars['tlssecurity']) { NW_TlsSecurityMode = parseInt(urlvars['tlssecurity']); }
            if (urlvars['ignoretls']) { NW_TlsSecurityMode = 0; }
            if (urlvars['skiptlshostcheck']) { NW_SkipTlsHostnameCheck = parseInt(urlvars['skiptlshostcheck']); }
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{DesktopClipboard}
            if (urlvars['kvmclip']) { QV('id_DeskKvmClipButton', true); }
            // ###END###{DesktopClipboard}

            // ###BEGIN###{ContextMenus}
            document.onclick = function (e) { hideContextMenu(); }
            // ###END###{ContextMenus}

            // ###BEGIN###{SessionRecording}
            srec_cleanup();
            Q('srec_PlaySpeed').value = 1;
            // ###END###{SessionRecording}

            // ###BEGIN###{Mode-LMS}
            // Setup LMS
            lms = CreateLmsControl();
            lms.onStateChanged = lmsChangedState;
            lms.onData = lmsOnData;
            lms.Start();
            QH('id_lmsData', LoadingHtml);
            QH('id_lmsData', '');
            QH('id_computername', 'Configuration Console v' + version);
            go(101);
            lmsRefresh();
            // ###END###{Mode-LMS}

            // ###BEGIN###{WsmanBrowser}
            // Add all WSMAN objects to WSMAN browser
            for (var w in AllWsman) { var option = document.createElement('option'); option.text = AllWsman[w]; option.id = 'WSB-' + AllWsman[w]; Q('id_QuerySelect').add(option); }
            // ###END###{WsmanBrowser}

            // ###BEGIN###{Desktop}
            // Setup the remote desktop
            desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk', Q('id_mainarea')));
            desktop.onStateChanged = onDesktopStateChange;
            QE('idx_connectbutton1', true);
            try { t = localStorage.getItem('desktopsettings'); } catch (ex) {}
            if (t) { desktopsettings = JSON.parse(t); }
            if (urlvars.kvmenc) { var v = parseInt(urlvars.kvmenc); if (typeof v == 'number') { desktopsettings.encflags = v; } }
            if (urlvars.kvmdec) { var v = parseInt(urlvars.kvmdec); if (typeof v == 'number') { desktopsettings.decimationMode = v; } }
            applyDesktopSettings();
            var s = '';
            //for (var c = 1; c < 13; c++) s += '<option value="' + (0xffbd + c) + '">F' + c +;
            //QH('specialkeylist', s);
            // ###END###{Desktop}

            // ###BEGIN###{Terminal}
            // Setup the terminal
            terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term'));
            terminal.onStateChanged = onTerminalStateChange;
            // ###BEGIN###{Terminal-Enumation-All}
            Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
            // ###END###{Terminal-Enumation-All}
            Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?"CR + LF":"LF";

            QE('idx_connectbutton2', true);

            // Setup Terminal drag & drop
            Q('p13').addEventListener('dragover', haltEvent, false);
            Q('p13').addEventListener('dragleave', haltEvent, false);
            Q('p13').addEventListener('drop', terminal_FileSelectHandler, false);
            // ###END###{Terminal}

            // Main drag & drop
            document.addEventListener('dragover', haltEvent, false);
            document.addEventListener('dragleave', haltEvent, false);
            document.addEventListener('drop', documentFileSelectHandler, false);

            // ###BEGIN###{Certificates}
            // Setup Terminal drag & drop
            Q('p16').addEventListener('dragover', haltEvent, false);
            Q('p16').addEventListener('dragleave', haltEvent, false);
            Q('p16').addEventListener('drop', cert_FileSelectHandler, false);
            // ###END###{Certificates}

            // ###BEGIN###{CertificateManager}
            // Setup Certificate Manager drag & drop
            Q('id_certManagerPanel').addEventListener('dragover', haltEvent, false);
            Q('id_certManagerPanel').addEventListener('dragleave', haltEvent, false);
            Q('id_certManagerPanel').addEventListener('drop', cert_importCertOk2, false);
            // ###END###{CertificateManager}

            // ###BEGIN###{CertificateManager}
            cert_loadCertificates();
            cert_updateCertificateList();
            // ###END###{CertificateManager}

            // ###BEGIN###{FileSaver}
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!Mode-NodeWebkit}
            if (!Q('Desk')['toBlob']) { QV('idx_deskSaveBtn', false); }// On some browsers like IE, we can't save screen shots. Hide the sceeenshot/capture buttons.
            // ###END###{!Mode-NodeWebkit}
            // ###END###{Desktop}
            // ###END###{FileSaver}

            // ###BEGIN###{ComputerSelector}

            if (!urlvars['host']) { go(101); }
            QH('id_computername', format("Console di gestione remota v{0}", version));

            // ###BEGIN###{ComputerSelector-Local}
            if (urlvars['host']) {
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                // If host is set to a hostname, connect directly to that computer
                var xuser = urlvars['user'];
                if (!xuser) xuser = '*'; // If user not set, default to * and use Kerberos
                var xpass = urlvars['pass'];
                if (!xpass) xpass = ''; // If password not set, default to blank.
                var xtls = 0;
                if (urlvars['tls'] == 1) { xtls = 1; }

                currentcomputer = { 'host': urlvars['host'], 'host': urlvars['host'], 'user': xuser, 'pass': xpass, 'tls': xtls, 'h': Math.random() };
                // ###BEGIN###{Mode-NodeWebkit}
                currentcomputer['tlscerthash'] = getCertPinning(urlvars['host']); // If we have a pinned TLS cert, add it here.
                // ###END###{Mode-NodeWebkit}
                disconnecturl = urlvars['disconnecturl'];
                if (!disconnecturl) disconnecturl = 'none';
                if (disconnecturl == 'none') QV('disconnectButton', false);
                if (disconnecturl == 'close') Q('disconnectButton').value = 'Close';
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                if ((currentcomputer['user'] == '*') || (currentcomputer['pass'] != '')) {
                    // Don't prompt the user for password, just connect. This is Kerberos or password already provided.
                    connect(ports.host, ports.http, currentcomputer['user'], currentcomputer['pass'], currentcomputer['tls']);
                } else {
                    // Prompt the user for digest password.
                    computerlist = [currentcomputer];
                    updateComputerList();
                    computerConnect(null, currentcomputer.h);
                }

                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                updateComputerList();
                // ###END###{ComputerSelector-Local-ScriptOnly}
            }
                // ###BEGIN###{!Mode-NodeWebkit}
            else if (urlvars['connect']) { loadServerComputer(); }
                // ###END###{!Mode-NodeWebkit}
            else {
                // ###BEGIN###{Mode-NodeWebkit}
                if (urlvars['list']) {
                    // Read the computers from a file list
                    var listok = 0;
                    try {
                        var ctext = require('fs').readFileSync(urlvars['list'], 'utf8');
                        if ((ctext.length > 2) && (ctext.charCodeAt(0) == 65533) && (ctext.charCodeAt(1) == 65533)) { // This is unicode detection
                            ctext = require('fs').readFileSync(urlvars['list'], 'utf16le');
                            if ((ctext.length > 1) && (ctext.charCodeAt(0) == 65279)) { ctext = ctext.substring(1); }
                        }
                        if (ctext) {
                            computerlist = JSON.parse(ctext);
                            if (computerlist.computers) { computerlist = computerlist.computers; }
                            var pins = getCertPinnings();
                            for (var i in computerlist) {
                                computerlist[i].checked = false;
                                if (!computerlist[i]['h']) computerlist[i]['h'] = Math.random(); // If 'h' handle is not present, create one.
                                if (!computerlist[i]['tls']) computerlist[i]['tls'] = 0; // If TLS is not present, assume 0.
                                if (!computerlist[i]['host'] && computerlist[i]['fqdn']) computerlist[i]['host'] = computerlist[i]['fqdn'];
                                if (!computerlist[i]['pass'] == null) computerlist[i]['pass'] = '';
                                if (computerlist[i]['fqdn']) delete computerlist[i]['fqdn'];

                                // Add stored certificate pinning.
                                if ((computerlist[i]['tlscerthash'] == null) && (pins[computerlist[i]['host']] != null)) { computerlist[i]['tlscerthash'] = pins[computerlist[i]['host']]; }
                                delete computerlist[i]['tlscert2'];
                                delete computerlist[i]['tlscerthash2'];
                            }
                            listok = computerlist.length;
                            if (listok > 0) updateComputerList();
                        }
                    } catch (e) { messagebox("Elenco dei computer", "File elenco non valido: " + e) }
                    // Run a script on all computers
                    if (urlvars['script'] && listok > 0) {
                        // Select all computers
                        for (var i in computerlist) { Q('SJ-' + computerlist[i]['h']).checked = true; }
                        // Run the script
                        try {
                            var data = require('fs').readFileSync(urlvars['script'], 'utf8');
                            if (data) { mscript_onScriptRead( { target: { result: data }}, 1 ); }
                        } catch (e) { messagebox("Esegui script", "File di script non valido.") }
                    }
                } else {
                    // Setup the computer selector
                    loadComputers();
                }
                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{!Mode-NodeWebkit}
                // Setup the computer selector
                loadComputers();
                // ###END###{!Mode-NodeWebkit}
            }
            // ###END###{ComputerSelector-Local}

            // ###BEGIN###{ComputerSelector-Remote}
            // Load the list of computers from the server
            loadServerComputerList();
            // ###END###{ComputerSelector-Remote}

            // ###END###{ComputerSelector}

            // ###BEGIN###{Mode-Firmware}
            connect('/wsman');
            // ###END###{Mode-Firmware}

            // ###BEGIN###{USBSetup}
            usb_displaySetupBin();

            // Add all possible variable types to dialog 16
            var options = '';
            for (var i in AmtSetupBinVarIds) { for (var j in AmtSetupBinVarIds[i]) { options += '<option value="' + i + '-' + j + '">' + AmtSetupBinVarIds[i][j][1] } }
            QH('d16type', options);
            // ###END###{USBSetup}

            document.onkeyup = handleKeyUp;
            document.onkeydown = handleKeyDown;
            document.onkeypress = handleKeyPress;
            window.onresize = center;
            center();

            // ###BEGIN###{Mode-NodeWebkit}
            NW_WindowTitle = require('nw.gui').Window.get().title;
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{Scripting-Editor}
            // ###BEGIN###{!Mode-Firmware}
            scriptLoadStartingBlocks();
            // ###END###{!Mode-Firmware}
            // ###END###{Scripting-Editor}

            // ###BEGIN###{Mode-NodeWebkit}
            NW_AutoUpdateCheck();
            // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
            if (urlvars['help'] || urlvars['?']) { messagebox("Opzioni linea comandante", '<div style=text-align:left><b>-host:[hostname]</b>, ' + "Nome host o IP di Intel&reg; AMT" + '<br/><b>-user:[username]</b>, ' + "Digest nome utente di accesso" + '<br/><b>-pass:[password]</b>, ' + "Digest password di accesso" + '<br/><b>-tls</b>, ' + "Connetti usando la sicurezza TLS" + '<br/><b>-kvm</b>, ' + "Una volta connesso, vai al desktop remoto" + '<br/><b>-kvmfull</b>, ' + "Una volta connesso, vai al desktop remoto a schermo intero" + '<br/><b>-kvmonly</b>, ' + "Esegui solo desktop remoto a schermo intero" + '<br/><b>-sol</b>, ' + "Una volta connesso, vai al terminale" + '<br/><b>-script:[file]</b>, ' + "Esegui uno script" + '<br/><b>-autoexit</b>, ' + "Esci al termine dello script" + '<br/><b>-ignoretls</b>, ' + "Non controllare il certificato Intel&reg; AMT TLS" + '<br/></div>'); }
            // ###END###{!ComputerSelector-Local-ScriptOnly}
            // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
            if (urlvars['help'] || urlvars['?']) { messagebox("Opzioni linea comandante", '<div style=text-align:left><b>-list:[listfile]</b>, ' + "List of computers to run a script on" + '<br/><b>-script:[file]</b>, ' + "Esegui uno script" + '<br/><b>-autoexit</b>, ' + "Exit after all scripts are done" + '<br/><b>-ignoretls</b>, ' + "Non controllare il certificato Intel&reg; AMT TLS" + '<br/></div>'); }
            // ###END###{ComputerSelector-Local-ScriptOnly}
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{DesktopInbandFiles}
            // Setup upload drag & drop
            Q('p24filetable').addEventListener('drop', p24fileDragDrop, false);
            Q('p24filetable').addEventListener('dragover', p24fileDragOver, false);
            Q('p24filetable').addEventListener('dragleave', p24fileDragLeave, false);
            // ###END###{DesktopInbandFiles}

            // ###BEGIN###{DesktopRecorder}
            if (urlvars && urlvars['norecord']) { QV('id_DeskRecorderTools', false); }
            // ###END###{DesktopRecorder}

            // ###BEGIN###{Mode-NodeWebkit}
            // Check input arguments
            if (urlvars['webcn'] == 1) { delete urlvars['webcn']; setTimeout(function() { alert('Invalid webcn argument, use -webcn:domain.com.'); }, 100); }
            // ###END###{Mode-NodeWebkit}
        }

        // ###BEGIN###{PowerControl-Advanced}
        // ###BEGIN###{PowerControl-OneClick}
        function setupWebServer(leafCN) {
            if ((webserver != null) && (webserver.certCommonName == leafCN)) return;

            // Stop the web server if present
            if (webserver != null) { webserver.stop(); webserver = null; }

            // Create a web server to serve One Client Recovery (OCR) disk image files.
            webserver = CreateWebServer();
            webserver.generateCertificate(leafCN);
            webserver.start();
            webserver.onTransfers = function (webserver, transfers) {
                var x = '';
                for (var i in transfers) { x += '<div style="width:350px;position:relative;padding:3px"><span style="position:absolute;padding:3px;font-weight:bold">' + transfers[i].xfilename + '</span><div style="height:20px;background-color:#4CAF50;width:' + Math.floor((transfers[i].progress.count * 100) / transfers[i].xsize) + '%;border-radius:4px"></div></div>'; }
                QV('TransferNotification', transfers.length > 0);
                QH('TransferNotification', x);
            }

            //console.log('WebServer Cert Hash RAW', webserver.certHashRaw);
            //console.log('WebServer Cert Hash HEX', webserver.certHashHex);
        }
        // ###END###{PowerControl-OneClick}
        // ###END###{PowerControl-Advanced}

        function documentFileSelectHandler(e) {
            haltEvent(e);
            // ###BEGIN###{IDER}
            var diskimages = true;
            for (var i = 0; i < e.dataTransfer.files.length; i++) {
                if ((e.dataTransfer.files[i].name.toLowerCase().endsWith('.img') == false) && (e.dataTransfer.files[i].name.toLowerCase().endsWith('.iso') == false)) { diskimages = false; }
            }
            if ((diskimages == true) && (e.dataTransfer != null) && (currentView > 0) && (currentView < 100) && ((e.dataTransfer.files.length == 1) || (e.dataTransfer.files.length == 2))) {
                var floppyfile = null, cdromfile = null;
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.iso')) { cdromfile = e.dataTransfer.files[0]; }
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.img')) { floppyfile = e.dataTransfer.files[0]; }
                if (e.dataTransfer.files.length == 2) {
                    if (e.dataTransfer.files[1].name.toLowerCase().endsWith('.iso')) { cdromfile = e.dataTransfer.files[1]; }
                    if (e.dataTransfer.files[1].name.toLowerCase().endsWith('.img')) { floppyfile = e.dataTransfer.files[1]; }
                }
                if ((floppyfile != null) || (cdromfile != null)) iderStart3(floppyfile, cdromfile, 1);
                return;
            }
            // ###END###{IDER}

            if (e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
            var f = null, filename = e.dataTransfer.files[0].name.toLowerCase();
            // ###BEGIN###{Storage}
            if (currentView == 21) { UploadToStorage(e.dataTransfer.files[0], filename); return; }
            // ###END###{Storage}
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                if (filename.endsWith('.mescript') || filename.endsWith('.meblocks')) { f = mscript_onScriptRead; }
                if (filename.endsWith('.json') || filename.endsWith('.csv')) { f = function (file) { onComputerListRead(file, filename); } }
            }
            // ###END###{ComputerSelector-Local}
            // ###BEGIN###{USBSetup}
            if (currentView == 102 && filename.endsWith('.bin')) { f = usb_onSetupBinRead; }
            // ###END###{USBSetup}
            // ###BEGIN###{Scripting}
            if (wsstack != null && (filename.endsWith('.mescript') || filename.endsWith('.meblocks'))) { f = script_onScriptRead; }
            // ###END###{Scripting}
            // ###BEGIN###{SessionRecording}
            if (currentView == 104 && filename.endsWith('.mcrec')) { srec_ondrop(e); return; }
            // ###END###{SessionRecording}
            if (f != null) { var reader = new FileReader(); reader.onload = f; reader.readAsBinaryString(e.dataTransfer.files[0]); }
        }

// ###BEGIN###{Mode-NodeWebkit}

        // ###BEGIN###{Look-Commander}
        function NW_CheckForUpdateMenu() {
            if (NW_UpdateMenuItem.checked == true) { NW_AutoUpdateCheck(); }
            try { localStorage.setItem('checkForUpdate', NW_UpdateMenuItem.checked); } catch (ex) { }
        }
        // ###END###{Look-Commander}

        // ###BEGIN###{Look-BrandedCommander}
        function NW_CheckForUpdateMenu() {
            if (NW_UpdateMenuItem.checked == true) { NW_AutoUpdateCheck(); }
            try { localStorage.setItem('checkForUpdate', NW_UpdateMenuItem.checked); } catch (ex) { }
        }
        // ###END###{Look-BrandedCommander}

        // Check if an update is available
        function NW_AutoUpdateCheck() {
            // ###BEGIN###{Look-Commander}
            // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
            try {
                if (localStorage.getItem('checkForUpdate') != 'false') {
                    var request = new XMLHttpRequest();
                    request.onload = function () {
                        if (request.status >= 200 && request.status < 400) {
                            var x = request.responseText, i = x.indexOf('##3B356F7A-0854-4EBA-B10D-4CC4FB522695##');
                            if (i > 0) {
                                x = x.substring(i);
                                var newversion = parseInt(x.substring(40, 46));
                                var criticalversion = parseInt(x.substring(48, 54));
                                var url = x.substring(56);
                                var j = url.indexOf('##');
                                if (j >= 0) {
                                    url = url.substring(0, j);
                                    var currentversion = version.split('.');
                                    currentversion = parseInt(currentversion[0] * 10000) + parseInt(currentversion[1] * 100) + parseInt(currentversion[2]);
                                    if (currentversion < newversion) {
                                        var newversiontext = Math.floor(newversion / 10000) + '.' + (Math.floor(newversion / 100) % 100) + '.' + (newversion % 100);
                                        var msg = format("MeshCommander v {0} è disponibile", newversiontext);
                                        if (currentversion < criticalversion) {
                                            msg += ", è un aggiornamento di sicurezza critico";
                                            QS('UpdateNotification')['background-color'] = 'orange';
                                        }
                                        QH('UpdateNotificationText', msg);
                                        QV('UpdateNotification', true);
                                    }
                                }
                            }
                        }
                    };
                    request.onerror = function () { console.log('Failed to get script blocks'); };
                    request.open('GET', 'https://sites.google.com/site/opensoftwareprojects/mesh/security-1/autoupdate', true);
                    request.send();
                }
            } catch (ex) { }
            // ###END###{!ComputerSelector-Local-ScriptOnly}
            // ###END###{Look-Commander}
            // ###BEGIN###{Look-BrandedCommander}
            try {
                if (localStorage.getItem('checkForUpdate') != 'false') {
                    var request = new XMLHttpRequest();
                    request.onload = function () {
                        if (request.status >= 200 && request.status < 400) {
                            var x = request.responseText, i = x.indexOf('##371cff53-32b7-4278-86c5-3e6906965332##');
                            if (i > 0) {
                                x = x.substring(i);
                                var newversion = parseInt(x.substring(40, 46));
                                var criticalversion = parseInt(x.substring(48, 54));
                                var url = x.substring(56);
                                var j = url.indexOf('##');
                                if (j >= 0) {
                                    url = url.substring(0, j);
                                    var currentversion = version.split('.');
                                    currentversion = parseInt(currentversion[0] * 10000) + parseInt(currentversion[1] * 100) + parseInt(currentversion[2]);
                                    if (currentversion < newversion) {
                                        var newversiontext = Math.floor(newversion / 10000) + '.' + (Math.floor(newversion / 100) % 100) + '.' + (newversion % 100);
                                        var msg = format("Intel&reg; Manageability Commander v{0} is available", newversiontext);
                                        if (currentversion < criticalversion) {
                                            msg += ", è un aggiornamento di sicurezza critico";
                                            QS('UpdateNotification')['background-color'] = 'orange';
                                        }
                                        QH('UpdateNotificationText', msg);
                                        QV('UpdateNotification', true);
                                    }
                                }
                            }
                        }
                    };
                    request.onerror = function () { console.log('Failed to get script blocks'); };
                    request.open('GET', 'https://software.intel.com/en-us/articles/intel-manageability-commander', true);
                    request.send();
                }
            } catch (ex) { }
            // ###END###{Look-BrandedCommander}
        }

        function NW_HideUpdateNotification() {
            QV('UpdateNotification', false);
        }

        function NW_PerformUpdate() {
            require('nw.gui').Shell.openExternal('http://www.meshcommander.com/meshcommander');
        }

        var NW_WindowTitle = null;
        var NW_UpdateMenuItem = null;
        var NW_AmtScanMenuItem = null;
        var NW_TlsSecurityMode = 1;
        var NW_SkipTlsHostnameCheck = 0;

        function NW_SetupMainMenu(x) {
            var gui = require('nw.gui');
            var mainmenu = new gui.Menu({ type: 'menubar' });
            
            // Add Mac OS X specific menu
            var os = require('os');
            if (os.platform() == 'darwin') { mainmenu.createMacBuiltin('MeshCommander', { hideEdit: true, hideWindow: true }); }
            var filemenu = new gui.MenuItem({ label: "File" });
            var filemenusub = new gui.Menu();
            var seperator = false;
            var toolsmenu = null;
            var scriptmenu = null;
            var securitymenu = null;
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer == null) {
            // ###END###{MeshServerConnect}
            if (x == 101) {
                // Computer selector
                filemenusub.append(new gui.MenuItem({ label: "Aggiungi computer Intel AMT ...", click: addComputer }));
                filemenusub.append(new gui.MenuItem({ label: "Carica computer ...", click: NW_LoadComputers }));
                filemenusub.append(new gui.MenuItem({ label: "Salva computer ...", click: NW_SaveComputers }));
                // ###BEGIN###{ComputerSelectorScanner}
                filemenusub.append(new gui.MenuItem({ label: "Ricerca computer ...", click: showScanDialog }));
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{MeshServerConnect}
                filemenusub.append(new gui.MenuItem({ type: 'separator' }));
                filemenusub.append(new gui.MenuItem({ label: "Connetti a MeshCentral ...", click: showMeshCentralConnectDialog }));
                // ###END###{MeshServerConnect}
                seperator = true;
            }
            // ###BEGIN###{MeshServerConnect}
            } else {
                filemenusub.append(new gui.MenuItem({ label: "Disconnetti da MeshCentral", click: meshCentralDisconnect }));
                seperator = true;
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{USBSetup}
            if (x == 102) {
                // Setup.bin Editor
                filemenusub.append(new gui.MenuItem({ label: "Nuovo...", click: usb_newSetupBin }));
                filemenusub.append(new gui.MenuItem({ label: "Carica Setup.bin ...", click: NW_LoadSetupBin }));
                filemenusub.append(new gui.MenuItem({ label: "Salva Setup.bin ...", click: usb_saveSetupBin }));
                seperator = true;
            }
            // ###END###{USBSetup}

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer == null) {
            // ###END###{MeshServerConnect}
            if (x >= 101 && x <= 104) {
                // Tools
                toolsmenu = new gui.MenuItem({ label: "Utensili" });
                var toolsmenusub = new gui.Menu();
                toolsmenusub.append(new gui.MenuItem({ label: "Gestione informatica", click: NW_ComputerManagement, type: 'checkbox', checked: (x == 101) }));
                // ###BEGIN###{CertificateManager}
                toolsmenusub.append(new gui.MenuItem({ label: "Gestione certificati", click: NW_CertificateManager, type: 'checkbox', checked: (x == 103) }));
                // ###END###{CertificateManager}
                // ###BEGIN###{USBSetup}
                toolsmenusub.append(new gui.MenuItem({ label: "Manager Setup.bin", click: NW_SetupBinEditor, type: 'checkbox', checked: (x == 102) }));
                // ###END###{USBSetup}
                // ###BEGIN###{SessionRecording}
                toolsmenusub.append(new gui.MenuItem({ label: "Session Player", click: NW_SessionPlayer, type: 'checkbox', checked: (x == 104) }));
                // ###END###{SessionRecording}
                toolsmenu.submenu  = toolsmenusub;
            }
            // ###BEGIN###{Scripting}
            // ###BEGIN###{!Look-BrandedCommander}
            if (x == 101) {
                // Batch Scripting
                scriptmenu = new gui.MenuItem({ label: "copione" });
                var scriptmenusub = new gui.Menu();
                if (computersRunningScripts > 0) {
                    scriptmenusub.append(new gui.MenuItem({ label: "Ferma tutti gli script", click: mscript_runScriptDlg }));
                } else {
                    scriptmenusub.append(new gui.MenuItem({ label: "Avvia script ...", click: mscript_runScriptDlg }));
                }
                scriptmenu.submenu  = scriptmenusub;
            }
            if (x >= 0 && x < 100) {
                // Computer Scripting
                scriptmenu = new gui.MenuItem({ label: "copione" });
                var scriptmenusub = new gui.Menu();
                if (scriptstate) {
                    scriptmenusub.append(new gui.MenuItem({ label: "Stop Script", click: script_Stop }));
                } else {
                    scriptmenusub.append(new gui.MenuItem({ label: "Avvia script ...", click: script_runScriptDlg }));
                }
                scriptmenu.submenu  = scriptmenusub;
            }
            // ###END###{!Look-BrandedCommander}
            // ###END###{Scripting}

            if (x == 101) {
                // Security
                securitymenu = new gui.MenuItem({ label: "Sicurezza" });
                var securitymenusub = new gui.Menu();
                securitymenusub.append(new gui.MenuItem({ label: "Ignora il certificato TLS", click: NW_ChangeTlsSecurityMode0, type: 'checkbox', checked: (NW_TlsSecurityMode == 0) }));
                securitymenusub.append(new gui.MenuItem({ label: "Visualizza certificato TLS & pin", click: NW_ChangeTlsSecurityMode1, type: 'checkbox', checked: (NW_TlsSecurityMode == 1) }));
                securitymenusub.append(new gui.MenuItem({ type: 'separator' }));
                NW_SkipTlsHostnameMenuItem = new gui.MenuItem({ label: "Salta il controllo del nome host TLS", click: NW_SkipTlsHostnameCheck0, type: 'checkbox', checked: (NW_SkipTlsHostnameCheck == 1) })
                securitymenusub.append(NW_SkipTlsHostnameMenuItem);
                securitymenu.submenu  = securitymenusub;
            }
            // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}

            if (x >= 0 && x < 100 && disconnecturl != 'none' && disconnecturl != 'close') {
                // Computer screen
                filemenusub.append(new gui.MenuItem({ label: "Disconnect", click: disconnect }));
                seperator = true;
            }
            
            // Explicit exit action not required on Mac. The MacBuiltin menu includes native option to quit application (Quit)
            if (os.platform() != 'darwin') {
                if (seperator == true) filemenusub.append(new gui.MenuItem({ type: 'separator' }));
                filemenusub.append(new gui.MenuItem({ label: "Uscita", click: NW_Exit }));
            }

            filemenu.submenu  = filemenusub;
            if (x == 13) {
                // Terminal
                toolsmenu = new gui.MenuItem({ label: "terminale" });
                var toolsmenusub = new gui.Menu();
                if (terminal.State == 0) {
                    toolsmenusub.append(new gui.MenuItem({ label: "Collegare", click: connectTerminal }));
                } else {
                    toolsmenusub.append(new gui.MenuItem({ label: "Disconnect", click: connectTerminal }));
                }
                // ###BEGIN###{FileSaver}
                toolsmenusub.append(new gui.MenuItem({ type: 'separator' }));
                if (terminal.m.capture == null) {
                    // ###BEGIN###{!TerminalReplay}
                    toolsmenusub.append(new gui.MenuItem({ label: "Avvia acquisizione", click: terminalCaptureToggle }));
                    // ###END###{!TerminalReplay}
                    // ###BEGIN###{TerminalReplay}
                    if (terminalReplayTimer == null) {
                        toolsmenusub.append(new gui.MenuItem({ label: "Avvia acquisizione", click: terminalCaptureToggle }));
                        toolsmenusub.append(new gui.MenuItem({ label: "Replay Capture", click: terminalReplay }));
                    } else {
                        toolsmenusub.append(new gui.MenuItem({ label: "Ferma la riproduzione", click: terminalReplay }));
                    }
                    // ###END###{TerminalReplay}
                } else {
                    toolsmenusub.append(new gui.MenuItem({ label: "Stop Capture", click: terminalCaptureToggle }));
                }
                // ###END###{FileSaver}
                toolsmenu.submenu  = toolsmenusub;
            }
            if (x == 14) {
                // Desktop
                toolsmenu = new gui.MenuItem({ label: "Desktop" });
                var toolsmenusub = new gui.Menu();
                if (desktop.State == 0) {
                    toolsmenusub.append(new gui.MenuItem({ label: "Collegare", click: connectDesktop }));
                } else {
                    toolsmenusub.append(new gui.MenuItem({ label: "Disconnect", click: connectDesktop }));
                }
                toolsmenusub.append(new gui.MenuItem({ type: 'separator' }));
                toolsmenusub.append(new gui.MenuItem({ label: "impostazioni", click: showDesktopSettings }));
                toolsmenu.submenu  = toolsmenusub;
            }

            // Language menu
            var languagemenu = new gui.MenuItem({ label: "Lingue" });
            var languagesubmenu = new gui.Menu();
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'en'), label: "inglese", click: function () { window.location.href = 'commander.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'zh-chs'), label: "Cinese semplificato)", click: function () { window.location.href = 'commander_zh-chs.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'nl'), label: "olandese", click: function () { window.location.href = 'commander_nl.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'fr'), label: "francese", click: function () { window.location.href = 'commander_fr.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'de'), label: "Tedesco", click: function () { window.location.href = 'commander_de.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'it'), label: "italiano", click: function () { window.location.href = 'commander_it.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'ja'), label: "giapponese", click: function () { window.location.href = 'commander_ja.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'pt'), label: "portoghese", click: function () { window.location.href = 'commander_pt.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'ru'), label: "russo", click: function () { window.location.href = 'commander_ru.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'es'), label: "spagnolo", click: function () { window.location.href = 'commander_es.htm'; } }));
            languagemenu.submenu = languagesubmenu;

            var helpmenu = new gui.MenuItem({ label: "Aiuto" });
            var helpmenusub = new gui.Menu();
            // ###BEGIN###{Look-Commander}
            var checkForUpdateCheck = false;
            try { checkForUpdateCheck = (localStorage.getItem('checkForUpdate') == 'false') ? false : true; } catch (ex) {}
            NW_UpdateMenuItem = new gui.MenuItem({ type: 'checkbox', checked: checkForUpdateCheck, label: "Controlla gli aggiornamenti", click: NW_CheckForUpdateMenu })
            helpmenusub.append(NW_UpdateMenuItem);
            // ###END###{Look-Commander}
            // ###BEGIN###{Look-BrandedCommander}
            var checkForUpdateCheck = false;
            try { checkForUpdateCheck = (localStorage.getItem('checkForUpdate') == 'false') ? false : true; } catch (ex) { }
            NW_UpdateMenuItem = new gui.MenuItem({ type: 'checkbox', checked: checkForUpdateCheck, label: "Controlla gli aggiornamenti", click: NW_CheckForUpdateMenu })
            helpmenusub.append(NW_UpdateMenuItem);
            // ###END###{Look-BrandedCommander}
            // ###BEGIN###{ComputerSelectorScanner}
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer == null) {
            // ###END###{MeshServerConnect}
            var amtPresenceScan = true;
            try { amtPresenceScan = (localStorage.getItem('scanForComputers') == 'false') ? false : true; } catch (ex) { }
            NW_AmtScanMenuItem = new gui.MenuItem({ type: 'checkbox', checked: amtPresenceScan, label: "Cerca presenza", click: NW_AmtScanMenu })
            helpmenusub.append(NW_AmtScanMenuItem);
            if (amtPresenceScan == true) { globalAmtScanner.start(); }
            // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}
            // ###END###{ComputerSelectorScanner}
            helpmenusub.append(new gui.MenuItem({ label: "Ripristina", click: NW_Reload }));
            if (urlvars['debug']) { helpmenusub.append(new gui.MenuItem({ label: "Mostra debug ...", click: NW_Debug })); }
            // ###BEGIN###{Look-ISDU}
            helpmenusub.append(new gui.MenuItem({ type: 'separator' }));
            helpmenusub.append(new gui.MenuItem({ label: "About...", click: WM_About }));
            // ###END###{Look-ISDU}
            // ###BEGIN###{Look-BrandedCommander}
            helpmenusub.append(new gui.MenuItem({ type: 'separator' }));
            helpmenusub.append(new gui.MenuItem({ label: "About...", click: WM_About }));
            // ###END###{Look-BrandedCommander}
            helpmenu.submenu  = helpmenusub;
            mainmenu.append(filemenu);
            if (toolsmenu != null) mainmenu.append(toolsmenu);
            if (scriptmenu != null) mainmenu.append(scriptmenu);
            if (securitymenu != null) mainmenu.append(securitymenu);
            mainmenu.append(languagemenu);
            mainmenu.append(helpmenu);
            gui.Window.get().menu = mainmenu;
        }

        function NW_Exit() {
            require('nw.gui').Window.get().close(); // Closes only the current window.
            //require('nw.gui').App.quit(); // Closes all instances of the app.
        }
        function NW_Reload() { require('nw.gui').Window.get().reloadIgnoringCache(); }
        function NW_Debug() { require('nw.gui').Window.get().showDevTools(); }

        function NW_ChangeTlsSecurityMode0() { NW_TlsSecurityMode = 0; try { localStorage.setItem('TlsSecurityMode', NW_TlsSecurityMode); } catch (ex) { } NW_SetupMainMenu(currentView); }
        function NW_ChangeTlsSecurityMode1() { NW_TlsSecurityMode = 1; try { localStorage.setItem('TlsSecurityMode', NW_TlsSecurityMode); } catch (ex) { } NW_SetupMainMenu(currentView); }
        function NW_SkipTlsHostnameCheck0() { NW_SkipTlsHostnameCheck = NW_SkipTlsHostnameMenuItem.checked ? 1 : 0; try { localStorage.setItem('SkipTlsHostnameCheck', NW_SkipTlsHostnameCheck); } catch (ex) { } NW_SetupMainMenu(currentView); }
        function NW_LoadComputers() {
            var chooser = Q('idx_d17computerlistfile');
            if (chooser.getAttribute('eventset') != 1) {
                chooser.setAttribute('eventset', '1');
                chooser.addEventListener('change', NW_LoadComputersEx, false);
            }
            chooser.value = null;
            chooser.click();
        }
        function NW_LoadComputersEx(evt) {
            var reader = new FileReader();
            reader.onload = function(file) { onComputerListRead(file, Q('idx_d17computerlistfile').files[0].name); }
            reader.readAsBinaryString(this.files[0]);
        }

        function NW_SaveComputers() { saveComputerList(); }
        function NW_ComputerManagement() { toolmenuclick(-1); go(101); }
        // ###BEGIN###{CertificateManager}
        function NW_CertificateManager() { toolmenuclick(-1); go(103); }
        // ###END###{CertificateManager}
        function NW_SetupBinEditor() { toolmenuclick(-1); go(102); }
        // ###BEGIN###{SessionRecording}
        function NW_SessionPlayer() { toolmenuclick(-1); go(104); }
        // ###END###{SessionRecording}

        function NW_LoadSetupBin() {
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('accept', '.bin');
            chooser.addEventListener('change', NW_LoadSetupBinEx, false);
            chooser.value = null;
            chooser.click();
        }
        function NW_LoadSetupBinEx() {
            var reader = new FileReader();
            reader.onload = function(file) { usb_onSetupBinRead(file); }
            reader.readAsBinaryString(this.files[0]);
        }

        // ###BEGIN###{Look-ISDU}
        function WM_About() {
            var x = { 'position': 'center', 'focus': true, 'frame': true, 'icon': 'favicon.png', 'width': 520, 'height': 320 };
            if (process.version == 'v1.2.0') x['toolbar'] = false;
            require('nw.gui').Window.open('about.htm', x);
        }
        // ###END###{Look-ISDU}

        // ###BEGIN###{Look-BrandedCommander}
        function WM_About() {
            var x = { 'position': 'center', 'focus': true, 'frame': true, 'icon': 'favicon.png', 'width': 520, 'height': 320 };
            if (process.version == 'v1.2.0') x['toolbar'] = false;
            require('nw.gui').Window.open('about.htm', x);
        }
        // ###END###{Look-BrandedCommander}

// ###END###{Mode-NodeWebkit}

// ###BEGIN###{ComputerSelector}
        // Load the list of computers from the server
        function loadServerComputerList() {
            var request = new XMLHttpRequest();
            request.onload = function() {
                if (request.status >= 200 && request.status < 400) {
                    // Success
                    var serverComputerList = JSON.parse(request.responseText);
                    if (serverComputerList && serverComputerList != null && serverComputerList instanceof Array) {
                        currentcomputer = null;
                        computerlist = [];
                        for (var i in serverComputerList) {
                            var computer = serverComputerList[i];
                            if (computer['host']) {
                                computer.checked = false;
                                if (!computer['h']) computer['h'] = Math.random(); // If 'h' handle is not present, create one.
                                if (!computer['tls']) computer['tls'] = 0; // If TLS is not present, assume 0.
                                computerlist.push(computer);
                            }
                        }
                        updateComputerList();
                    }
                } else {
                    console.log('Failed to get server computer list');
                }
            };

            request.onerror = function() {
                console.log('Failed to get server computer list');
            };

            // ###BEGIN###{ComputerSelector-Remote}
            request.open('GET', 'webrelay.ashx?action=getcomputerlist', true);
            // ###END###{ComputerSelector-Remote}
            // ###BEGIN###{ComputerSelector-Local}
            request.open('GET', urlvars['connect'], true);
            // ###END###{ComputerSelector-Local}
            request.send();
        }
// ###END###{ComputerSelector}

// ###BEGIN###{Mode-LMS}
        // Called when the LMS control channel changes state
        function lmsChangedState(sender, state)
        {
            //console.log("LMS Control Channel State: " + state);
            if (state == 0) { 
                setDialogMode();
                QV('id_lmsToolBarContent', false);
                QH('id_lmsData', '<div style=text-align:center;padding-top:20px>' + "MicroLMS disconnected." + '<div>');
                QH('id_lmsData2', '');
            } else if (state == 2) { QV('id_lmsToolBarContent', true); lmsRefresh(); }
        }

        function lmsLogin() { window.location.href = '/authindex.html'; }

        var lmsProvisioningStates = ["Pre-Provisioning", "In-Provisioning", "Post-Provisioning"];
        var lmsProvisioningModes = ["Nessuna", "Enterprise Mode", "Small Buisness Mode", "Remote Assistance Mode"];
        var lmsMeInfo = null;
        var lmsTemp = null;
        var lmsNotifications = null;

        // Called when data is received on the LMS control channel
        function lmsOnData(sender, data)
        {
            var cmdid = ReadShortX(data, 0);
            //console.log("LMS Control Channel Data: " + data + ", cmdid:" + cmdid);

            switch (+cmdid) {
                case 1: { // ME Information
                    //console.log(data.substring(2));
                    var meinfo = JSON.parse(data.substring(2));
                    QV('id_lmsLoginButton', meinfo['LoginMode'] == 1);

                    // If Intel AMT is in-between states, reload data in a few seconds.
                    if ((meinfo['TrustedHashes'] != null) && (meinfo['ProvisioningMode'] == -858993460)) {
                        QV('id_lmsConfigureButton', false);
                        QV('id_lmsActivateButton', false);
                        QV('id_lmsDeactivateButton', false);
                        setTimeout(lmsRefresh, 1000);
                        return;
                    }

                    lmsMeInfo = meinfo;
                    if (meinfo['ProvisioningState'] == null) {
                        QH('id_lmsData', '<div style=text-align:center;padding-top:20px>' + "Intel&reg; AMT not found" + '<div>');
                        QH('id_lmsData2', '');
                    } else {
                        meinfo['Flags'] = +meinfo['Flags'];

                        var x = '<h2>' + "Current Status" + '</h2>';
                        x += TableStart();
                        if (meinfo['ProvisioningState'] != 2) {
                            x += TableEntry("Activation state", lmsProvisioningStates[meinfo['ProvisioningState']]);
                        } else {
                            if (meinfo['Flags'] & 2) { x += TableEntry("Activation state", "Activated in Client Control Mode"); }
                            else if (meinfo['Flags'] & 4) { x += TableEntry("Activation state", "Activated in Admin Control Mode"); }
                            else { x += TableEntry("Activation state", "Activated, " + lmsProvisioningModes[meinfo['ProvisioningMode']]); }
                        }
                        x += TableEntry("Intel&reg; AMT version", addLink(meinfo['Versions']['AMT'], 'lmsShowVersionsDlg()'));
                        if (meinfo['MeiVersion'] != null) { x += TableEntry("Intel&reg; MEI driver version", meinfo['MeiVersion']); }
                        x += TableEnd();

                        if (meinfo['ProvisioningState'] != 2) {
                            x += '<h2>' + "Activation Information" + '</h2>';
                            x += TableStart();
                            if (meinfo['DnsSuffix']) {
                                x += TableEntry("Trusted DNS suffix", meinfo['DnsSuffix']);
                            } else {
                                x += TableEntry("Trusted DNS suffix", '<i>' + "Not Set" + '</i>');
                            }
                            if (meinfo['TrustedHashes'] != null) {
                                if (meinfo['TrustedHashes'].length == 1) {
                                    x += TableEntry("Trusted hashes", addLink(meinfo['TrustedHashes'].length + ' hash', 'lmsShowTrustedHashesDlg()'));
                                } else {
                                    x += TableEntry("Trusted hashes", addLink(meinfo['TrustedHashes'].length + ' hashes', 'lmsShowTrustedHashesDlg()'));
                                }
                            }
                            x += TableEnd();
                        }

                        QH('id_lmsData', x);
                        QV('id_lmsData2', true);
                        lmsNotifications = meinfo['Notifications'].reverse();
                        lmsRefreshNotifications();
                        QV('id_lmsConfigureButton', (meinfo['ProvisioningState'] == 2)); // Only display the "Login..." button if Intel AMT is in post-provisioning state.
                        QV('id_lmsActivateButton', (meinfo['ProvisioningState'] == 0) && (meinfo['LoginMode'] >= 2)); // Only display the "Activate..." button if Intel AMT is in pre-provisioning state and we are adrministrator.
                        QV('id_lmsDeactivateButton', (meinfo['ProvisioningState'] == 2) && (meinfo['Flags'] & 2) && (meinfo['LoginMode'] >= 2)); // Only display the "Deactivate..." button if Intel AMT is in port-provisioning state & in client control mode & we are adrministrator.
                    }
                    break;
                }
                case 2: { // Intel ME Un-Provisioning
                    lmsDeactivateX2(ReadIntX(data, 2));
                    break;
                }
                case 3: { // Intel ME System Account Information
                    var status = ReadIntX(data, 2);
                    if (status != 0) {
                        messagebox("Attivazione Intel&reg; AMT", format("Failed to get account information, status {0}", status));
                    } else {
                        var meuser = data.substring(6, data.indexOf('\0', 6));
                        var mepass = data.substring(39, data.indexOf('\0', 39));
                        QH('id_dialogMessage', "Fetching activation status...");
                        wsstack = WsmanStackCreateService("localhost", 16992, meuser, mepass, false);
                        amtstack = AmtStackCreateService(wsstack);
                        amtstack.onProcessChanged = onProcessChanged;
                        amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], lmsActivationX1);
                    }
                    break;
                }
                case 9: { // New notification
                    var notification = JSON.parse(data.substring(2));
                    if (lmsNotifications == null) { lmsNotifications = []; }
                    lmsNotifications.unshift(notification);
                    lmsRefreshNotifications();
                    if ((notification.code == 'iAMT0055-0') || (notification.code == 'iAMT0055-1') || (notification.code == 'iAMT0055-2')) { setDialogMode(); lmsRefresh(); }
                    break;
                }
            }
        }

        function lmsRefreshNotifications() {
            var x = '<h2>' + "Notifications" + '</h2>' + TableStart();
            if (lmsNotifications && lmsNotifications.length > 0) {
                for (var i in lmsNotifications) {
                    var n = lmsNotifications[i], v = n.str;
                    if (n.code != 'iAMT0050-32') {
                        if (v.indexOf('User Notification Alert - ') == 0) { v = v.substring(26); }
                        x += TableEntry(new Date(n.date).toLocaleString(), v);
                    }
                }
            } else {
                x += '<tr><td style=padding:8px><i>' + "No notifications found." + '</i><td>';
            }
            x += TableEnd();
            QH('id_lmsData2', x);
        }

        function lmsActivationX1(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Attivazione Intel&reg; AMT", format("Failed to fetch activation status, status {0}", status));
            } else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) {
                messagebox("Attivazione Intel&reg; AMT", "Client control mode activation not allowed");
            } else {
                lmsTemp = responses['AMT_GeneralSettings'].response;
                amtstack.IPS_HostBasedSetupService_Setup(2, rstr2hex(rstr_md5('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + d4password.value)), null, null, null, null, lmsActivationX2);
            }
        }

        function lmsActivationX2(stack, name, response, status) {
            if (status != 200 || response.Body['ReturnValue'] != 0) {
                messagebox("Attivazione Intel&reg; AMT", format("Failed activation, status {0}", status));
            } else {
                setDialogMode();
                lmsRefresh();
                lmsTemp['HostName'] = lmsMeInfo['OsHostname']; // Set the OS hostname
                // TODO: Also set the local FQDN if we can get it from LMS
                wsstack = WsmanStackCreateService('localhost', 16992, 'admin', d4password.value, false);
                amtstack = AmtStackCreateService(wsstack);
                amtstack.onProcessChanged = onProcessChanged;
                amtstack.Put('AMT_GeneralSettings', lmsTemp, function() { }, 0, 1);
            }
        }

        function lmsDeactivate() {
            if (xxdialogMode || lms.State != 2) return;
            QH('id_dialogMessage', "Confirm Intel&reg; AMT deactivation?");
            setDialogMode(1, "Intel&reg; AMT Deactivation", 3, lmsDeactivateX1);
        }

        function lmsDeactivateX1() {
            statusbox("Intel&reg; AMT Deactivation", "Deactivating Intel&reg; AMT...");
            lms.SendCmd(2, IntToStrX(1)); // Send request for deactivation
        }

        function lmsDeactivateX2(status) {
            if (status != 0) {
                messagebox("Intel&reg; AMT Deactivation", format("Failed deactivation, status ", status));
            } else {
                QH('id_lmsData', "Please wait for deactivation...");
                QV('id_lmsData2', false);
                setDialogMode();
                lmsRefresh();
            }
        }

        // Refresh button on the UI
        function lmsRefresh() {
            if (lms.State != 2) return;
            lms.SendCmd(1, ''); // Send the request basic information command
        }

        // Configure button on the UI
        function lmsConfigure() {
            if (xxdialogMode) return;
            setDialogMode(4, "Intel&reg; AMT Login", 3, function () { lmsConfigureLogin(); });
            //d4username.readOnly = false;
            d4username.disabled = false;
            if (d4username.value == 'admin') d4username.value = '';
            inputBoxFocus('d4username');
            lmsUpdateLoginDialog();
        }

        // Called when the user hits OK on the login dialog
        function lmsConfigureLogin() {
            var user = d4username.value;
            if (user == '') user = 'admin';
            connect('localhost', 16992, user, d4password.value, 0);
        }

        // Activate button on the UI
        function lmsActivate() {
            if (xxdialogMode|| lms.State != 2) return;
            setDialogMode(4, "Attivazione Intel&reg; AMT", 3, function () { lmsActivateEx(); });
            //d4username.readOnly = true;
            d4username.disabled = true;
            d4username.value = 'admin';
            inputBoxFocus('d4password');
            lmsUpdateLoginDialog();
        }

        // Go head with Intel AMT client control mode activation
        function lmsActivateEx()
        {
            lms.SendCmd(3); // Send request for account information
            statusbox("Attivazione Intel&reg; AMT", "Fetching Account Information...");
        }

        // Called each time something changes in the login dialog
        function lmsUpdateLoginDialog(e, d) {
            var ok = passwordcheck(d4password.value);
            QE('idx_dlgOkButton', ok);
            if (e != null && e.keyCode == 13 && d == 1) inputBoxFocus('d4password');
            if (ok == true && e != null && e.keyCode == 13 && d == 2) dialogclose(1);
        }

        var lmsHashArgStrings = ["MD5", "SHA1", "SHA256", "SHA512"];
        function lmsShowTrustedHashesDlg() {
            // {\"AC\":%d,\"DF\":%d,\"AL\":%d,\"NA\":\"%s\",\"HA\":\"%s\"}"

            var x = '<div style=max-height:240px;overflow-y:scroll>' + TableStart();
            for (var i in lmsMeInfo['TrustedHashes'])
            {
                //x += '<b>' + lmsMeInfo['TrustedHashes'][i]['Name'] + '</b><br><span style=font-size:10px>' + lmsHashArgStrings[lmsMeInfo['TrustedHashes'][i]['HashAlgorithm']] + (lmsMeInfo['TrustedHashes'][i]['Active'] == 1?", Active":'') + (lmsMeInfo['TrustedHashes'][i]['Default'] == 1?", Default":'') + '</span><br><span style=font-size:10px>' + lmsMeInfo['TrustedHashes'][i]['Hash'] + '</span><br><br>';
                x += TableEntry('<b>' + lmsMeInfo['TrustedHashes'][i]['Name'] + '</b><br><span style=font-size:10px>' + lmsHashArgStrings[lmsMeInfo['TrustedHashes'][i]['HashAlgorithm']] + (lmsMeInfo['TrustedHashes'][i]['Active'] == 1?", Active":'') + (lmsMeInfo['TrustedHashes'][i]['Default'] == 1?", Default":'') + '</span><br><span style=font-size:8px>' + lmsMeInfo['TrustedHashes'][i]['Hash'] + '</span>', '');
            }
            x += TableEnd() + '</div>';
            messagebox("Intel&reg; AMT Trusted Hashes", x);
        }

        function lmsShowVersionsDlg() {
            var x = TableStart();
            x += TableEntry("Intel&reg; AMT", lmsMeInfo['Versions']['AMT']);
            if (lmsMeInfo['MeiVersion'] != null) { x += TableEntry("Intel&reg; MEI driver", lmsMeInfo['MeiVersion']); }
            for (var i in lmsMeInfo['Versions']) { if (i != 'AMT') x += TableEntry(i, lmsMeInfo['Versions'][i]); }
            x += TableEnd();
            messagebox("Intel&reg; AMT Versions", x);
        }

// ###END###{Mode-LMS}

// ###BEGIN###{Mode-MeshCentral2}
        function connectButtonfunction() {
            if (!wsstack || wsstack.socketState == 0) { meshcentral2credCallback(); } else { disconnect(); }
        }

        function connectButtonfunctionEx() {
            currentMeshNode = parent.getCurrentNode();
            connect(currentMeshNode._id, 16992, null, null, 0);
            Q('xconnectbutton1').value = "Disconnect";
        }

        function getCurrentMeshNode() { return currentMeshNode; }
        function setConnectionState(isConnectable) { QE('xconnectbutton1', isConnectable); if (isConnectable == false) { disconnect(); } }
        function setFrameHeight(height) {
            //console.log('setFrameHeight', height);
            //QS('entireBody').height = height;
        }
        function setAuthCallback(updateAmtCredentials) { meshcentral2credCallback = updateAmtCredentials; }
        function setUrlVar(name, value) { if (!urlvars) { urlvars = {}; } urlvars[name] = value; }
// ###END###{Mode-MeshCentral2}

        function cleanup() {
            // ###BEGIN###{Terminal}
            // ###BEGIN###{FileSaver}
            // ###BEGIN###{!Mode-NodeWebkit}
            idx_terminalCaptureButton.value = "Avvia acquisizione";
            // ###END###{!Mode-NodeWebkit}
            if (terminal.m.capture) delete terminal.m.capture;
            // ###END###{FileSaver}
            terminal.Stop();
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            desktop.disconnectCode = 0;
            desktop.Stop();
            // ###END###{Desktop}
        }

        function handleKeyUp(e) {
            if (xxdialogMode) return;
            // ###BEGIN###{ComputerSelector}
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer == null) {
                // ###END###{MeshServerConnect}
                    if (e.keyCode == 45) { addComputer(); } // Insert key
                    if (e.keyCode == 46) { deleteComputers(); } // Delete key
                // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}
                if ((e.keyCode == 65) && (e.ctrlKey == true)) { selectAllComputers(); } // Select all
                if (e.keyCode == 13) { if (computersRunningScripts == 0) { computerConnect(event, currentcomputer.h); } } // Enter key
                if ((e.keyCode == 8) && !filterFocus) { var x = Q('computerFilter').value; Q('computerFilter').value = (x.substring(0, x.length - 1)); computerFilterFunc(); }
                if (e.keyCode == 27) { Q('computerFilter').value = ''; computerFilterFunc(); }
            }
            // ###END###{ComputerSelector-Local}
            // ###BEGIN###{ComputerSelector-Remote}
            if (currentView == 101) {
                if ((e.keyCode == 65) && (e.ctrlKey == true)) { selectAllComputers(); } // Select all
            }
            // ###END###{ComputerSelector-Remote}
            // ###END###{ComputerSelector}
            // ###BEGIN###{CertificateManager}
            if (currentView == 103) {
                //if (e.keyCode == 45) { addComputer(); } // Insert key
                if (e.keyCode == 46) { cert_deleteCertificates(); } // Delete key
                //if ((e.keyCode == 65) && (e.ctrlKey == true)) { selectAllCertificates(); } // Select all
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (!Q('id_DeskVO').checked) { return desktop.m.handleKeyUp(e); } }
            // ###END###{!DesktopInband}
            // ###BEGIN###{DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (Q('id_DeskVO').checked) return; if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.handleKeyUp(e); desktop.m.sendKeepAlive(); } else { return desktop.m.handleKeyUp(e); } }
            // ###END###{DesktopInband}
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (currentView == 13 && terminal.State == 3) return terminal.m.TermHandleKeyUp(e);
            // ###END###{Terminal}
        }

        function handleKeyDown(e) {
            //console.log('handleKeyDown', e);
            if (xxdialogMode) return;
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (!Q('id_DeskVO').checked) { return desktop.m.handleKeyDown(e); } }
            // ###END###{!DesktopInband}
            // ###BEGIN###{DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (Q('id_DeskVO').checked) return; if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.handleKeyDown(e); desktop.m.sendKeepAlive(); } else { return desktop.m.handleKeyDown(e); } }
            // ###END###{DesktopInband}
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (currentView == 13 && terminal.State == 3) return terminal.m.TermHandleKeyDown(e);
            // ###END###{Terminal}
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                if (e.keyCode == 38) { var selectprev = null; for (var y in computerlist) { if (currentcomputer.h == computerlist[y].h) { if (selectprev != null) { computerSelect(null, selectprev); } } else { selectprev = computerlist[y].h; } } } // Up key
                if (e.keyCode == 40) { var selectnext = 0; for (var y in computerlist) { if (selectnext == 1) { selectnext = 2; computerSelect(null, computerlist[y].h); } else { if (currentcomputer.h == computerlist[y].h) { selectnext = 1; } } } } // Down key
            }
            // ###END###{ComputerSelector-Local}
        }

        function handleKeyPress(e) {
            //console.log('handleKeyPress', e);
            if (xxdialogMode) return;
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                if ((!filterFocus) && (e.keyCode != 0)) { Q('computerFilter').value = ((Q('computerFilter').value + String.fromCharCode(e.keyCode))); computerFilterFunc(); }
            }
            // ###END###{ComputerSelector-Local}
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (!Q('id_DeskVO').checked) { return desktop.m.handleKeys(e); } }
            // ###END###{!DesktopInband}
            // ###BEGIN###{DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (Q('id_DeskVO').checked) return; if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.handleKeys(e); desktop.m.sendKeepAlive(); } else { return desktop.m.handleKeys(e); } }
            // ###END###{DesktopInband}
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (currentView == 13 && terminal.State == 3) return terminal.m.TermHandleKeys(e);
            // ###END###{Terminal}
            // ###BEGIN###{SessionRecording}
            if (currentView == 104) {
                if (e.keyCode == 32) { srec_togglePause(); haltEvent(e); }
                if (e.keyCode == 49) { Q('srec_PlaySpeed').value = 4; haltEvent(e); }
                if (e.keyCode == 50) { Q('srec_PlaySpeed').value = 2; haltEvent(e); }
                if (e.keyCode == 51) { Q('srec_PlaySpeed').value = 1; haltEvent(e); }
                if (e.keyCode == 52) { Q('srec_PlaySpeed').value = 0.5; haltEvent(e); }
                if (e.keyCode == 53) { Q('srec_PlaySpeed').value = 0.25; haltEvent(e); }
                if (e.keyCode == 54) { Q('srec_PlaySpeed').value = 0.1; haltEvent(e); }
                if (e.keyCode == 48) { srec_pause(); srec_restart(); haltEvent(e); }
            }
            // ###END###{SessionRecording}
        }

        var connectFunc = null;
        var connectFuncTag = null;
        function connect(host, port, user, pass, tls, func, functag) {
            go(0);
            fullscreenonly = false;
            connectFunc = func;
            connectFuncTag = functag;

            // ###BEGIN###{Desktop}
            if (urlvars['kvm'] == 1) { go(14); }
            if ((urlvars['kvmfull'] == 1) || (urlvars['kvmonly'] == 1)) { go(14); deskToggleFull(urlvars['kvmonly'] == 1); }
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (urlvars['sol'] == 1) { go(13); }
            // ###END###{Terminal}

            // ###BEGIN###{Mode-NodeWebkit}
            var tlsoptions = {};
            // ###BEGIN###{CertificateManager}

            // Create a list of trusted certificates in PEM format
            var trustedCertStringsPem = [];
            for (var y in certificateStore) {
                var certificate = certificateStore[y];
                if (certificate['trusted'] == true) { trustedCertStringsPem.push('-----BEGIN CERTIFICATE-----\n' + certificate['certbin'] + '\n-----END CERTIFICATE-----\n'); }
            }
            tlsoptions.ca = trustedCertStringsPem;

            // Setup out console TLS authentication certificate
            var authcert = getTlsAuthCertificate();
            if (authcert != null) {
                tlsoptions.cert = forge.pki.certificateToPem(authcert['cert']);
                tlsoptions.key = forge.pki.privateKeyToPem(authcert['privateKey']);
            }

            // ###END###{CertificateManager}

            // ###BEGIN###{!MeshServerConnect}
            wsstack = WsmanStackCreateService(host, port, user, pass, tls, tlsoptions);
            // ###END###{!MeshServerConnect}
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                wsstack = WsmanStackCreateService(currentcomputer._id, null, null, null, 0, meshCentralServer);
            } else {
                wsstack = WsmanStackCreateService(host, port, user, pass, tls, tlsoptions);
            }
            // ###END###{MeshServerConnect}

            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            wsstack = WsmanStackCreateService(host, port, user, pass, tls);
            // ###END###{!Mode-NodeWebkit}
            amtstack = AmtStackCreateService(wsstack);
            amtstack.onProcessChanged = onProcessChanged;

            // Setup TLS checking
            // ###BEGIN###{Mode-NodeWebkit}
            wsstack.comm.xtlsSkipHostCheck = NW_SkipTlsHostnameCheck;
            if (NW_TlsSecurityMode == 0) { wsstack.comm.xtlsFingerprint = 0; }
            else { wsstack.comm.xtlsFingerprint = currentcomputer['tlscerthash'] ? currentcomputer['tlscerthash'] : currentcomputer['tlscerthash2']; }
            // ###END###{Mode-NodeWebkit}

            // Hide TLS indicator
            // ###BEGIN###{Mode-NodeWebkit}
            QV('tlsNotification1', false);
            QV('tlsNotification2', false);
            QV('tlsNotification3', false);
            QV('tlsNotification4', false);
            // ###END###{Mode-NodeWebkit}

            // Setup Digest Realm checking
            // ###BEGIN###{ComputerSelector}
            if (currentcomputer['digestrealm']) { wsstack.comm.digestRealmMatch = currentcomputer['digestrealm']; }
            // ###END###{ComputerSelector}

            // Hide most of the left menu options, we will see them as we load data
            for (var i = 2; i < 25; i++) { QV('go' + i, false); }
            QV('go8', true); // Network Settings
            // ###BEGIN###{Terminal}
            QV('go13', false); // Terminal
            // ###BEGIN###{!Mode-NodeWebkit}
            QE('TermWD', false);
            // ###END###{!Mode-NodeWebkit}
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            //QV('go14', false); // Desktop
            // ###END###{Desktop}
            //QV('go15', false); // Audit Log
            // ###BEGIN###{WsmanBrowser}
            QV('go12', true); // WSMAN Browser
            // ###END###{WsmanBrowser}
            // ###BEGIN###{Certificates}
            //QV('go16', false); // Security Settings
            // ###END###{Certificates}
            // ###BEGIN###{RemoteAccess}
            //QV('go17', false); // Remote Access
            // ###END###{RemoteAccess}
            // ###BEGIN###{Scripting-Editor}
            QV('go20', true); // Scripting Editor
            // ###END###{Scripting-Editor}

            // ###BEGIN###{Storage}
            // ###BEGIN###{Mode-Firmware}
            //QH('storagelinks', '');
            // ###END###{Mode-Firmware}
            // ###END###{Storage}

            // Clear the displayed power state
            // ###BEGIN###{Terminal}
            QH('id_p13power', ''); // Terminal
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            QH('id_p14power', ''); // Desktop
            // ###END###{Desktop}

            // Clear everything, make sure all connection state is reset.
            amtversion = amtversionmin = amtFirstPull = 0;
            amtsysstate = amtdeltatime = amtlogicalelements = HardwareInventory = undefined;
            amtPowerBootCapabilities = null;
            xxAccountFetch = 999;
            // ###BEGIN###{PowerControl}
            // ###BEGIN###{!Mode-MeshCentral2}

            if (!urlvars['norefresh']) { amtPowerPollTimer = setInterval(PullPowerState, 5000); }

            // ###END###{!Mode-MeshCentral2}
            // ###END###{PowerControl}

            // Show loading on all panels
            QH('id_TableSysStatus', LoadingHtml);
            // ###BEGIN###{NetworkSettings}
            QH('id_TableNetworkSettingsSpan', LoadingHtml);
            amtwirelessif = -1;
            // ###BEGIN###{Wireless}
            xxWireless = undefined;
            QH('id_TableWifi2', '');
            // ###END###{Wireless}
            // ###END###{NetworkSettings}
            // ###BEGIN###{HardwareInfo}
            QH('id_TableSysInfo', LoadingHtml);
            // ###END###{HardwareInfo}

            xxAccountAdminName = null;
            xxAccountRealmInfo = {};
            QH('id_TableUserAccounts', LoadingHtml);
            // ###BEGIN###{EventLog}
            eventmessages = null;
            QH('id_TableEventLog','');
            QH('id_TableEventLog2',LoadingHtml);
            // ###END###{EventLog}
            // ###BEGIN###{AuditLog}
            auditLog = null;
            QH('id_TableAuditLog1', '');
            QH('id_TableAuditLog2', LoadingHtml);
            // ###END###{AuditLog}
            // ###BEGIN###{Certificates}
            xxCertificates = null;
            QH('id_TableCerts', LoadingHtml);
            // ###END###{Certificates}
            // ###BEGIN###{WsmanBrowser}
            QH('id_wsresults', '');
            // ###END###{WsmanBrowser}
            // ###BEGIN###{IDER}
            iderStop();
            // ###END###{IDER}
            // ###BEGIN###{RemoteAccess}
            xxRemoteAccess = null;
            xxEnvironementDetection = null;
            xxCiraServers = null;
            xxUserInitiatedCira = null;
            xxRemoteAccessCredentiaLinks = null;
            xxMPSUserPass = null;
            xxPolicies = null;
            QH('id_TableRemoteAccess', LoadingHtml);
            // ###END###{RemoteAccess}
            // ###BEGIN###{AgentPresence}
            QH('id_TableSystemAgentPresence', LoadingHtml);
            // ###END###{AgentPresence}
            // ###BEGIN###{SystemDefense}
            xxSystemDefense = null;
            xxSystemDefenceLinkedPolicy = {};
            xxUpdatingDefenseStats = false;
            xxFilterStatistics = [{}, {}]; // Wired and wireless interface stats
            xxFilterStatisticsTimer = null;
            xxFilterStatisticsTimerActive = false;
            QH('id_TableSystemDefense', LoadingHtml);
            // ###END###{SystemDefense}
            // ###BEGIN###{Desktop}
            QE('id_DeskCAD', false);
            // ###BEGIN###{DesktopClipboard}
            QE('id_DeskKvmClipButton', false);
            // ###END###{DesktopClipboard}
            QE('DeskWD', false);
            QE('deskkeys', false);
            if (urlvars['kvmviewonly']) { QE('id_DeskVO', false); Q('id_DeskVO').checked = true; }
            // ###BEGIN###{DesktopType}
            QE('id_DeskType', false);
            // ###END###{DesktopType}
            // ###END###{Desktop}

            // ###BEGIN###{Desktop-Multi}
            desktopScreenInfo = null;
            // ###END###{Desktop-Multi}

            // Start pulling Intel AMT information
            amtstack.BatchEnum('', ['CIM_SoftwareIdentity', '*AMT_SetupAndConfigurationService'], processSystemVersion); // Get Intel AMT version information and plenty more
            //amtstack.Enum('CIM_LogicalElement', processSystemVersion); // Get Intel AMT version information and plenty more

            // ###BEGIN###{VersionWarning}
            QV('id_versionWarning', false);
            // ###END###{VersionWarning}

            // ###BEGIN###{Scripting-Editor}
            fupdatescript();
            // ###END###{Scripting-Editor}
        }

        function disconnect() {
            // ###BEGIN###{Desktop-Multi}
            if (desktopPollTimer != null) {clearInterval(desktopPollTimer); desktopPollTimer = null; }
            // ###END###{Desktop-Multi}

            // ###BEGIN###{Mode-NodeWebkit}
            if (urlvars['host']) {
                require('nw.gui').Window.get().close();
                //require('nw.gui').App.quit();
                return;
            }
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{Desktop}
            if (fullscreen) deskToggleFull();
            // ###END###{Desktop}

            // ###BEGIN###{IDER}
            iderStop();
            // ###END###{IDER}

            // ###BEGIN###{PowerControl}
            // ###BEGIN###{!Mode-MeshCentral2}
            if (amtPowerPollTimer != null) { clearInterval(amtPowerPollTimer); amtPowerPollTimer = null; }
            // ###END###{!Mode-MeshCentral2}
            // ###END###{PowerControl}

            // ###BEGIN###{SystemDefense}
            StopDefenseStatsTimer();
            // ###END###{SystemDefense}

            // ###BEGIN###{Scripting}
            script_Stop();
            // ###END###{Scripting}
            // ###BEGIN###{Scripting-Editor}
            breakScriptButton();
            // ###END###{Scripting-Editor}

            dialogclose(0);
            // ###BEGIN###{!Mode-MeshCentral2}
            QH('id_computername', '');
            // ###END###{!Mode-MeshCentral2}
            if (amtstack) {
                amtstack.onProcessChanged = null; // Un-hook progress indicator
                amtstack.CancelAllQueries(999); // Fail all pending WSMAN calls. Set to 999 to indicate not to call back any of the pending calls with errors.
                amtstack = null;
            }
            cleanup();
            wsstack = null;
            delete amtstack;
            onProcessChanged(0, 1);
            go(101);
            // ###BEGIN###{!Mode-MeshCentral2}

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                QH('id_computername', format("Console di gestione remota v{0}, Server: {1}", version, meshCentralServer.host));
            } else {
                QH('id_computername', format("Console di gestione remota v{0}", version));
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QH('id_computername', format("Console di gestione remota v{0}", version));
            // ###END###{!MeshServerConnect}
            
            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            require('nw.gui').Window.get().title = NW_WindowTitle;
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{Mode-MeshCentral2}
            Q('xconnectbutton1').value = "Collegare";
            QH('id_messageviewstr', "Disconnected");
            go(100);
            // ###END###{Mode-MeshCentral2}
        }

        function onProcessChanged(a, b) {
            QS('id_progressbar').width = ((a * 100) / b) + '%';
            if (a == 0) refreshButtons(true); // If nothing is being done, re-enable refresh buttons

            // ###BEGIN###{Mode-NodeWebkit}
            // Don't do any WSMAN if we don't need to do it.
            if ((urlvars['kvmonly'] == 1) || (fullscreenonly == true)) return;
            // ###END###{Mode-NodeWebkit}

            // If there is nothing being done now, see if we can pull more information
            if (a != 0 || !amtstack) return;
            if ((amtversion > 0) && ((amtFirstPull & 64) == 0)) {
                amtFirstPull |= 64;
                PullPowerPolicy();
                // ###BEGIN###{EventSubscriptions}
                subscriptionsFilters = null;
                PullEventSubscriptions();
                // ###END###{EventSubscriptions}
                // ###BEGIN###{AgentPresence}
                PullWatchdog();
                // ###END###{AgentPresence}

                // ###BEGIN###{Scripting-Editor}
                scriptViewButton(script_BuildingBlocks?1:0);
                // ###END###{Scripting-Editor}

                if (amtversion > 5) {
                    // ###BEGIN###{Certificates}
                    PullCertificates();
                    // ###END###{Certificates}
                    // ###BEGIN###{RemoteAccess}
                    PullRemoteAccess();
                    // ###END###{RemoteAccess}
                }
                return;
            }
            // ###BEGIN###{HardwareInfo}
            if ((amtFirstPull & 1) == 0) { PullHardware(); return; }
            // ###END###{HardwareInfo}
            // ###BEGIN###{EventLog}
            if ((amtFirstPull & 16) == 0) { PullEventLog(); return; }
            // ###END###{EventLog}
            // ###BEGIN###{AuditLog}
            if ((amtFirstPull & 32) == 0) { PullAuditLog(); return; }
            // ###END###{AuditLog}
        }

// ###BEGIN###{Mode-LMS}
        function toolmenuclick(x) {
            QV('id_menuitem1', currentView == 101);
            // ###BEGIN###{USBSetup}
            QV('id_menuitem2', currentView == 102);
            // ###END###{USBSetup}
            // ###BEGIN###{CertificateManager}
            QV('id_menuitem3', currentView == 103);
            // ###END###{CertificateManager}
            // ###BEGIN###{SessionRecording}
            QV('id_menuitem4', currentView == 104);
            // ###END###{SessionRecording}

            var d = (QS('id_computerSelectorMenu').display == 'none');
            if (d == true && xxdialogMode) return;
            xxdialogMode = (d == true)?999:undefined;
            QV('id_computerSelectorMenu', d);
            if (x == 0) return;
            go(x);
        }
// ###END###{Mode-LMS}

// ###BEGIN###{ComputerSelector}

        var computerlist = [];
        var currentcomputer = null;
        var computersRunningScripts = 0;

        function toolmenuclick(x) {
            QV('id_menuitem1', currentView == 101);
            // ###BEGIN###{USBSetup}
            QV('id_menuitem2', currentView == 102);
            // ###END###{USBSetup}
            // ###BEGIN###{CertificateManager}
            QV('id_menuitem3', currentView == 103);
            // ###END###{CertificateManager}
            // ###BEGIN###{SessionRecording}
            QV('id_menuitem4', currentView == 104);
            // ###END###{SessionRecording}

            var d = (QS('id_computerSelectorMenu').display == 'none');
            if (x == -1) { QV('id_computerSelectorMenu', false); xxdialogMode = undefined; return; }
            if (d == true && xxdialogMode) return;
            xxdialogMode = (d == true)?999:undefined;
            QV('id_computerSelectorMenu', d);
            if (x <= 0) return;
            go(x);
        }

        function computerFilterFunc() {
            var filter = computerFilter.value.toLowerCase();
            for (var w in computerlist) { QV('CX-' + computerlist[w].h, filter == '' || computerlist[w].checked == true || computerlist[w]['host'].toLowerCase().indexOf(filter) >= 0 || computerlist[w]['name'].toLowerCase().indexOf(filter) >= 0); }
        }

        // ###BEGIN###{ComputerSelector-Local}
        function addComputer() {
            if (xxdialogMode) return;

            // Build the list of groups
            var groups = [], x = '';
            for (var y in computerlist) { var computer = computerlist[y]; if ((computer.tags != null) && (computer.tags != '') && (groups.indexOf(computer.tags) == -1) && (computer.tags.indexOf('"') == -1)) { groups.push(computer.tags); } }
            groups.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
            for (var y in groups) { x += '<option value="' + groups[y] + '">'; }
            QH('d4devGroups', x);

            // Display the dialog box
            d4name.value = d4tags.value = d4hostname.value = d4password.value = '';
            d4username.value = "Admin";
            if (kerberos != null) {
                QH('d4security', '<option value=0>' + "Digest / Nessuno" + '</option><option value=1>' + "Digest / TLS" + '</option><option value=2>' + "Kerberos / Nessuno" + '</option><option value=3>' + "Kerberos / TLS" + '</option>');
            } else {
                QH('d4security', '<option value=0>' + "Digest / Nessuno" + '</option><option value=1>' + "Digest / TLS" + '</option>');
            }
            d4security.value = 0;
            setDialogMode(4, "Aggiungi computer", 3, function () { addComputerButton(); });
            updateComputerDialog();
            d4name.focus();
        }

        // Toggle the select of all computers
        // TODO: Fix problem with this combined with filter box
        function selectAllComputers() {
            var x = false;
            for (var y in computerlist) { if (computerlist[y].checked == false) { x = true; } }
            for (var y in computerlist) { computerlist[y].checked = x; Q('SJ-' + computerlist[y]['h']).checked = x; } // TODO: Only select or un-select when element is visible
        }

        function deleteComputers() {
            if (xxdialogMode) return;
            // Figure out how many computers are selected.
            var clist = [];
            for (var y in computerlist) { if (computerlist[y].checked == true) { clist.push(computerlist[y]); } }
            if (clist.length == 0) { clist.push(currentcomputer); }
            if (clist.length == 1) {
                setDialogMode(11, "Elimina computer", 3, deleteComputersEx, '<br>' + "Elimina il computer?", clist);
            } else {
                setDialogMode(11, "Elimina computer", 3, deleteComputersEx, '<br>' + format("Eliminare {0} computer?", clist.length), clist);
            }
        }

        function deleteComputersEx(button, clist) {
            for (var i in clist) {
                var handleToDelete = clist[i]['h'];
                if ((currentcomputer != null) && (currentcomputer['h'] == handleToDelete)) { currentcomputer = null; }
                for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == handleToDelete) { computerlist.splice(x, 1); } }
            }
            saveComputers();
            updateComputerList();
            updateComputerDetails();
        }

        function newComputerList() {
            if (xxdialogMode) return;
            QH('id_dialogMessage', "Clear list of known Intel&reg; AMT computers?");
            setDialogMode(1, "Nuovo elenco di computer", 3, newComputerListOk);
        }

        function newComputerListOk(r) {
            computerlist = [];
            currentcomputer = null;
            // ###BEGIN###{!Mode-NodeWebkit}
            idx_d18computerfilename.value = 'computerlist.json';
            // ###END###{!Mode-NodeWebkit}
            saveComputers();
            updateComputerList();
        }
        
        function openComputerList() {
            if (xxdialogMode) return;
            // ###BEGIN###{!Mode-NodeWebkit}
            setDialogMode(17, "Open Computer List", 3, openComputerListOk);
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = Q('idx_d17computerlistfile');
            if (chooser.getAttribute('eventset') != 1) {
                chooser.setAttribute('eventset', '1');
                chooser.addEventListener('change', NW_LoadComputersEx, false);
            }
            chooser.value = null;
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function openComputerListOk(r) {
            if (r != 1) return;
            var x = Q('idx_d17computerlistfile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = function(file) { onComputerListRead(file, Q('idx_d17computerlistfile').files[0].name); }
            reader.readAsBinaryString(x.files[0]);
        }
        
        function onComputerListRead(file, name, pass) {
            var x;
            if (name.toLowerCase().endsWith('.csv')) {
                // Load from a CSV file
                x = { computers: [] };
                var lines = file.target.result.split('\r\n').join('\n').split('\n'), headers = {}, count = 0;
                for (var i in lines) {
                    var values = lines[i].split(',');
                    if (i == 0) {
                        // Fill the headers
                        for (var j in values) {
                            if (values[j] == 'Intel AMT FQDN') { headers[j] = 'name'; }
                            if (values[j] == 'Intel AMT IPv4') { headers[j] = 'host'; }
                            if (values[j] == 'Intel AMT Version') { headers[j] = 'ver'; }
                            //if (values[j] == 'Last Connection Time') { headers[j] = 'date'; }
                        }
                    } else {
                        // Fill data
                        var computerEntry = {};
                        for (var j in values) {
                            if (headers[j] && (values[j].length > 0)) { computerEntry[headers[j]] = values[j]; }
                        }
                        if (computerEntry.host || computerEntry.name) {
                            if (computerEntry.host == null) { computerEntry.host = computerEntry.name; }
                            if (computerEntry.user == null) { computerEntry.user = 'admin'; }
                            if (computerEntry.pass == null) { computerEntry.pass = ''; }
                            if (computerEntry.tls == null) { computerEntry.tls = 1; }
                            x.computers.push(computerEntry);
                            count++;
                        }
                    }
                }
                if (count == 0) { x = {}; }
            } else {
                try { x = JSON.parse(file.target.result); } catch (ex) { }
                // ###BEGIN###{Mode-NodeWebkit}
                if (x && x['magic'] == '3209ruwpcoinaT4r9w347t0e4ug') {
                    if (pass) {
                        // Decrypt the file
                        x = getDecryptedData(x, pass);
                        if (x && (x != null)) { x = JSON.parse(x); }
                    } else {
                        // Prompt to the password
                        var x = "Il file selezionato richiede una password." + '<br/><br/><div style=height:26px><input id=idx_filepass type=password style=float:right;width:200px onkeyup=filePasswordDialogUpdate()><div>' + "Parola d'ordine" + '</div></div>';
                        setDialogMode(11, "Password del file", 3, onComputerListReadEx, x, [file, name]);
                        filePasswordDialogUpdate();
                        return;
                    }
                }
                // ###END###{Mode-NodeWebkit}
            }
            if (!x || !x['computers']) {
                messagebox("Apri il file", "File elenco computer non valido o danneggiato. Incapace di aprire.");
            } else {
                // ###BEGIN###{!Mode-NodeWebkit}
                idx_d18computerfilename.value = name;
                // ###END###{!Mode-NodeWebkit}
                currentcomputer = null;
                computerlist = x['computers'];
                for (var i in computerlist) { computerlist[i]['h'] = Math.random(); computerlist[i].checked = false; }
                updateComputerList();
                saveComputers();
            }
        }

        function onComputerListReadEx(button, tag) { onComputerListRead(tag[0], tag[1], Q('idx_filepass').value); }
        function filePasswordDialogUpdate() { QE('idx_dlgOkButton', passwordcheck(Q('idx_filepass').value)); }

        // ###BEGIN###{FileSaver}

        function saveComputerListUpdate() {
            var ok = true;
            // ###BEGIN###{Mode-NodeWebkit}
            QV('d18showpassword', d18usepassword.checked);
            if (d18usepassword.checked == true) { ok = (passwordcheck(d18password1.value) && (d18password1.value == d18password2.value)) };
            // ###END###{Mode-NodeWebkit}
            QE('idx_dlgOkButton', ok);
        }

        function saveComputerList() {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            d18usepassword.checked = false;
            d18password1.value = '';
            d18password2.value = '';
            // ###END###{Mode-NodeWebkit}
            setDialogMode(18, "Salva elenco computer", 3, saveComputerListOk);
            saveComputerListUpdate();
        }

        function saveComputerListOk() {
            var computerlist2 = Clone(computerlist);
            for (var i in computerlist2) { delete computerlist2[i]['h']; delete computerlist2[i].checked; delete computerlist2[i]['consolemsg']; }
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(JSON.stringify({ 'webappversion':version, 'computers':computerlist2 }, null, '  ').replace(/\n/g, '\r\n')), idx_d18computerfilename.value);
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', 'computerlist.json');
            chooser.addEventListener('change', function() {
                if (this.value == '') return;
                if (d18usepassword.checked == false) { 
                    require('fs').writeFile(this.value, JSON.stringify({ 'webappversion': version, 'computers': computerlist2 }, null, '  ').replace(/\n/g, '\r\n'), function () { });
                } else {
                    require('fs').writeFile(this.value, JSON.stringify(getEncryptedData(JSON.stringify({ 'webappversion': version, 'computers': computerlist2 }, null, '  '), d18password1.value), null, '  ').replace(/\n/g, '\r\n'), function () { });
                }
                this.value = '';
            }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function getEncryptedData(dataStr, password) {
            var crypto = require('crypto');
            var salt = crypto.randomBytes(16);
            var key = crypto.pbkdf2Sync(password, salt, 128000, 16, 'sha512');
            var iv = Math.round((Math.pow(36, 13) - Math.random() * Math.pow(36, 12))).toString(36).slice(1);
            var cipher = crypto.createCipheriv('aes-256-gcm', key.toString('hex'), iv);
            var encrypted = cipher.update(dataStr, 'utf8', 'hex') + cipher.final('hex');
            return { 'magic': '3209ruwpcoinaT4r9w347t0e4ug', 'version': 1, 'salt': salt.toString('hex'), 'iv': iv, 'tag': cipher.getAuthTag().toString('hex'), 'data': encrypted };
        }

        function getDecryptedData(encryptedData, password) {
            var crypto = require('crypto');
            var salt = new require('buffer').Buffer(encryptedData['salt'], 'hex');
            var iv = encryptedData['iv'];
            var tag = new require('buffer').Buffer(encryptedData['tag'], 'hex');
            var data = encryptedData['data'];
            var key = crypto.pbkdf2Sync(password, salt, 128000, 16, 'sha512');
            var decipher = crypto.createDecipheriv('aes-256-gcm', key.toString('hex'), iv);
            decipher.setAuthTag(tag);
            var decrypted = decipher.update(data, 'hex', 'utf8') + decipher.final('utf8');
            return decrypted;
        }

        // ###END###{FileSaver}

        function updateComputerDialog() {
            var k = Q('d4security').value >= 2;
            QV('d4digest', !k);
            QV('d4kerb', k);
            var hostSplit = d4hostname.value.split(':');
            var hostnameok = (d4hostname.value.length > 0) && (hostSplit.length < 3);
            if (hostnameok && (hostSplit.length == 2)) { var hostport = parseInt(hostSplit[1]); hostnameok = (hostport > 0) && (hostport < 65536) && (hostport == hostSplit[1]); }
            QS('d4hostname')['background-color'] = (hostnameok ? 'white' : 'LightYellow');
            if (k && hostnameok) {
                QE('idx_dlgOkButton', d4hostname.value.length > 0);
            } else {
                QS('d4username')['background-color'] = (((d4username.value.length > 0) && (d4username.value != '*')) ? 'white' : 'LightYellow');
                QS('d4password')['background-color'] = (((d4username.value == '$$OsAdmin') || passwordcheck(d4password.value) || d4password.value == '') ? 'white' : 'LightYellow');
                QE('idx_dlgOkButton', d4hostname.value.length > 0 && d4username.value.length > 0 && d4username.value != '*' && ((d4username.value == '$$OsAdmin') || passwordcheck(d4password.value) || d4password.value == ''));
            }
        }

        function addComputerButton() {
            var k = Q('d4security').value >= 2;
            // ###BEGIN###{!Mode-NodeWebkit}
            if (k) {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': '*', 'pass': encodeURIComponent(Q('d4kerberos').value), 'tls': d4security.value % 2 });
            } else {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': encodeURIComponent(d4username.value), 'pass': encodeURIComponent(d4password.value), 'tls': d4security.value % 2 });
            }
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            if (k) {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': '*', 'pass': encodeURIComponent(Q('d4kerberos').value), 'tls': d4security.value % 2, 'tlscerthash': getCertPinning(d4hostname.value) });
            } else {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': encodeURIComponent(d4username.value), 'pass': encodeURIComponent(d4password.value), 'tls': d4security.value % 2, 'tlscerthash': getCertPinning(d4hostname.value) });
            }
            // ###END###{Mode-NodeWebkit}
            saveComputers();
            updateComputerList();
        }

        function computerSelector_FileSelectHandler(e) {
            haltEvent(e);
            if (e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = function(file) { onComputerListRead(file, e.dataTransfer.files[0].name); }
            reader.readAsText(e.dataTransfer.files[0]);
        }

        function computerEdit(h) {
            if (xxdialogMode) return;
            var c = null;
            for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }

            // Build the list of groups
            var groups = [], x = '';
            for (var y in computerlist) { var computer = computerlist[y]; if ((computer.tags != null) && (computer.tags != '') && (groups.indexOf(computer.tags) == -1) && (computer.tags.indexOf('"') == -1)) { groups.push(computer.tags); } }
            groups.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
            for (var y in groups) { x += '<option value="' + groups[y] + '">'; }
            QH('d4devGroups', x);

            // If connected to a MeshCentral server, only edit the device name
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                var x = '<div style=height:26px><input id=d11deviceName style=float:right;width:200px value="' + decodeURIComponent(c['name'] ? c['name'] : '') + '"><div>' + "Nome amichevole" + '</div></div>';
                setDialogMode(11, "Modifica dispositivo", 3, computerEditMeshOk, x, c);
                return;
            }
            // ###END###{MeshServerConnect}

            if (kerberos != null || c['user'] == '*') {
                QH('d4security', '<option value=0>' + "Digest / Nessuno" + '</option><option value=1>' + "Digest / TLS" + '</option><option value=2>' + "Kerberos / Nessuno" + '</option><option value=3>' + "Kerberos / TLS" + '</option>');
            } else {
                QH('d4security', '<option value=0>' + "Digest / Nessuno" + '</option><option value=1>' + "Digest / TLS" + '</option>');
            }
            d4name.value = decodeURIComponent(c['name']?c['name']:'');
            d4tags.value = decodeURIComponent(c['tags']?c['tags']:'');
            d4hostname.value = decodeURIComponent(c['host']);
            d4security.value = c['tls'] + ((c['user'] == '*')?2:0);
            if (c['user'] == '*') {
                d4kerberos.value = decodeURIComponent(c['pass']?c['pass']:'');
            } else {
                d4username.value = decodeURIComponent(c['user']?c['user']:'');
                d4password.value = decodeURIComponent(c['pass']?c['pass']:'');
            }
            setDialogMode(4, "Modifica dispositivo", 7, function (r) { computerEditOk(r, h); });
            updateComputerDialog();
            Q('d4name').focus();
        }

        // ###BEGIN###{MeshServerConnect}
        function computerEditMeshOk(button, c) {
            if (Q('d11deviceName').value != c.name) { meshCentralServer.send({ action: 'changedevice', nodeid: c._id, name: Q('d11deviceName').value }); }
        }
        // ###END###{MeshServerConnect}

        function computerEditOk(r, h) {
            if (r == 2) { computerRemoveEx(h); return; }
            var c = null;
            for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            c['name'] = decodeURIComponent(d4name.value);
            c['tags'] = decodeURIComponent(d4tags.value);
            c['host'] = decodeURIComponent(d4hostname.value);
            if (d4security.value < 2) {
                // Digest authentication
                c['user'] = decodeURIComponent(d4username.value);
                c['pass'] = decodeURIComponent(d4password.value);
            } else {
                // Kerberos authentication
                c['user'] = '*';
                c['pass'] = decodeURIComponent(d4kerberos.value);
            }
            c['tls'] = d4security.value % 2;

            //for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { computerlist.splice(x, 1); } }
            //var c = { 'h': h, "name": d4name.value, "host": d4hostname.value, "user": d4username.value, "pass": d4password.value, "tls": d4security.value };
            //computerlist.push(c);
            //if (currentcomputer['h'] == c['h']) { currentcomputer = c; }
            saveComputers();
            //computerSelect();
            updateComputerList();
            updateComputerDetails();
        }

        function computerRemoveEx(h) {
            if (currentcomputer['h'] == h) currentcomputer = null;
            for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { computerlist.splice(x, 1); } }
            saveComputers();
            updateComputerList();
            updateComputerDetails();
        }

        function onFilterFocus(x) { filterFocus = x; }

        // ###END###{ComputerSelector-Local}

        function updateComputerList() {
            QH('id_computerList', '');
            // ###BEGIN###{MeshServerConnect}
            if ((meshCentralServer != null) && (computerlist.length == 0)) {
                QV('id_noKnownComputers', false);
                if (meshCentralServer.socketState < 3) {
                    QH('id_computerList', '<div style=width:99%;text-align:center;margin-top:36px;color:gray>' + "Connessione in corso ..." + '</div>');
                } else {
                    QH('id_computerList', '<div style=width:99%;text-align:center;margin-top:36px;color:gray>' + "Nessun computer Intel&reg; AMT trovato su questo account." + '</div>');
                }
                QV('id_noKnownComputers', false);
            } else {
                QV('id_noKnownComputers', computerlist.length == 0);
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QV('id_noKnownComputers', computerlist.length == 0);
            // ###END###{!MeshServerConnect}
            QV('computerFilter', computerlist.length != 0);
            // ###BEGIN###{FileSaver}
            QE('saveComputersButton', computerlist.length != 0);
            // ###END###{FileSaver}
            // ###BEGIN###{Scripting}
            computersRunningScripts = 0;
            var computersWithScriptsMsgs = 0;
            
            for (var y in computerlist) { if (computerlist[y].scriptstate) computersRunningScripts++; if (computerlist[y]['consolemsgs']) computersWithScriptsMsgs++; }
            // ###BEGIN###{Mode-NodeWebkit}
            if (urlvars['autoexit'] && computersRunningScripts == 0 && computersWithScriptsMsgs > 0) {
                require('nw.gui').Window.get().close();
                //require('nw.gui').App.quit();
                return;
            } // Exit if no scripts are running
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{ComputerSelectorToolbar}
            QE('idx_runScriptOnComputersButton', computerlist.length != 0);
            // ###BEGIN###{MeshServerConnect}
            QV('id_noScriptButtons', (computersRunningScripts == 0) && (meshCentralServer == null));
            QV('idx_disconnectMeshCentralButton', meshCentralServer != null);
            QV('idx_runScriptOnComputersButton', meshCentralServer == null);
            QV('toolmenuicondiv', meshCentralServer == null);
            // ###BEGIN###{Mode-NodeWebkit}
            QV('LeftMenuMyCerts', meshCentralServer == null);
            QV('LeftMenuMyUsb', meshCentralServer == null);
            QV('LeftMenuPlayer', meshCentralServer == null);
            // ###END###{Mode-NodeWebkit}
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QV('id_noScriptButtons', computersRunningScripts == 0);
            // ###END###{!MeshServerConnect}
            idx_runScriptOnComputersButton.value = (computersRunningScripts > 0 ? "Ferma tutti gli script" : "Esegui script ...")
            // ###END###{ComputerSelectorToolbar}
            // ###END###{Scripting}
            QV('id_computerDetailsParent', computerlist.length != 0);
            QS('id_computerListParent').right = (computerlist.length == 0 ? 0 : '300px');
            computerlist.sort(function (a, b) { var aa = a['name'] ? a['name'].toLowerCase() : a['host'].toLowerCase(); var bb = b['name'] ? b['name'].toLowerCase() : b['host'].toLowerCase(); if (aa > bb) { return 1; } if (aa < bb) { return -1; } return 0; });
            if (currentcomputer == null && computerlist.length > 0) { currentcomputer = computerlist[0]; }

            // Built a sorted list of groups
            var groups = [''], groupHtml = {};
            for (var y in computerlist) { var computer = computerlist[y]; if ((computer.tags != null) && (groups.indexOf(computer.tags) == -1)) { groups.push(computer.tags); } }
            groups.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
            for (var y in groups) { groupHtml[groups[y]] = ''; }

            // Go thru each computer and create the HTML entry
            for (var y in computerlist) {
                var computer = computerlist[y], extra = [], group = '', disabled = false;
                if (computer.tags != null) { group = computer.tags; }
                if (computer['user'] == '*') { extra.push("Kerberos"); } else { if (computer['user']) { extra.push(EscapeHtml(decodeURIComponent(computer['user']))); } }
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) {
                    var securityok = false;
                    if (computer['conn']) {
                        if ((computer['conn'] & 2) != 0) { extra.push("CIRA"); securityok = true; } else {
                            if ((computer['conn'] & 4) != 0) { extra.push("Diretto"); }
                            else if ((computer['conn'] & 8) != 0) { extra.push("staffetta"); }
                        }
                    }
                    if (securityok == true) {
                        if (computer['tls'] != 0) { extra.push("TLS"); }
                    } else {
                        extra.push((computer['tls'] == 0) ? NoBreak("Nessuna sicurezza") : "TLS");
                    }
                } else {
                    extra.push((computer['tls'] == 0) ? NoBreak("Nessuna sicurezza") : "TLS");
                }
                // ###END###{MeshServerConnect}
                // ###BEGIN###{!MeshServerConnect}
                extra.push((computer['tls'] == 0) ? NoBreak("Nessuna sicurezza") : "TLS");
                // ###END###{!MeshServerConnect}
                var name = decodeURIComponent(computer['host']);
                if (computer['name'] && computer['name'] != '') name = decodeURIComponent(computer['name']);

                var x = '<div id=CX-' + computer['h'] + ' ondblclick=computerEdit(' + computer['h'] + ')>';
                // ###BEGIN###{Look-Commander}
                // ###BEGIN###{ComputerSelectorScanner}
                var gray = false;
                if (NW_AmtScanMenuItem && (NW_AmtScanMenuItem.checked == true)) { gray = ((!globalAmtScanner.scanTable[computer['h']]) || (globalAmtScanner.scanTable[computer['h']].scanstate != 1)); }
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) { disabled = gray = ((computer.conn & 14) == 0); }
                // ###END###{MeshServerConnect}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div id=SI-' + computer['h'] + ' class=\"j' + (computer['icon'] ? computer['icon'] : 1) + (gray ? ' gray' : '') + '\" style=float:left;margin-left:4px;margin-right:4px></div>';
                // ###END###{!ComputerSelectorNoImages}
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{!ComputerSelectorScanner}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div id=SI-' + computer['h'] + ' class=\"j' + (computer['icon'] ? computer['icon'] : 1) + '\" style=float:left;margin-left:4px;margin-right:4px></div>';
                // ###END###{!ComputerSelectorNoImages}
                // ###END###{!ComputerSelectorScanner}
                // ###END###{Look-Commander}

                // ###BEGIN###{ComputerSelectorNoImages}
                x += '<div><table style="height:24px;width:calc(100%);margin:3px;cursor:pointer;border:none" cellspacing=0 cellpadding=0';
                // ###END###{ComputerSelectorNoImages}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div><table style="height:24px;width:calc(100% - 38px);margin:3px;cursor:pointer;border:none" cellspacing=0 cellpadding=0';
                // ###END###{!ComputerSelectorNoImages}

                // ###BEGIN###{ComputerSelector-Local}
                // ###BEGIN###{ContextMenus}
                var cmenus = [];
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                if ((computer.scriptstate == undefined) && (disabled == false)) {
                    cmenus.push("Collegare" + '#computerConnect(event,' + computer['h'] + ')');
                    cmenus.push("Windowed Connect" + '#computerConnect(event,' + computer['h'] + ',100)');
                    cmenus.push('-');
                    cmenus.push("Desktop" + '#computerConnect(event,' + computer['h'] + ',1)');
                    cmenus.push("Solo desktop" + '#computerConnect(event,' + computer['h'] + ',3)');
                    cmenus.push("terminale" + '#computerConnect(event,' + computer['h'] + ',4)');
                }
                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###BEGIN###{Scripting}
                if (computer.scriptstate != null) cmenus.push("Stop Script" + '#computerStopScript(event,' + computer['h'] + ')');
                if (computer['consolemsgs'] != null) cmenus.push("Uscita script ..." + '#mscript_showComputerScriptOutput(' + computer['h'] + ')');
                // ###END###{Scripting}
                if (computer.scriptstate == null) cmenus.push("Modificare..." + '#computerEdit(' + computer['h'] + ')');
                x += ' cm=\'' + cmenus.join('|') + '\'';
                // ###END###{ContextMenus}
                // ###END###{ComputerSelector-Local}
                x += ' onclick="computerSelect(event, ' + computer['h'] + ')" id=CI-' + computer['h'] + '>';
                x += '<td id=LCX-' + computer['h'] + ' class=g1 style=float:none>&nbsp;</td>' // Left side gray scale

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer == null) {
                // ###END###{MeshServerConnect}
                // ###BEGIN###{ComputerSelectorScanner}
                if (NW_AmtScanMenuItem && (NW_AmtScanMenuItem.checked == true)) {
                    var scanstate = globalAmtScanner.scanTable[computer['h']], scancolor = '';
                    if (scanstate) { if (scanstate.scanstate == 1) scancolor = ';background-color:green'; if (scanstate.scanstate == 0) scancolor = ';background-color:red'; }
                    x += '<td style=width:12px title="' + "Risposta Intel&reg; AMT RMCP" + '"><div id=SS-' + computer['h'] + ' class=computeritemcir style=' + scancolor + '></div>';
                }
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}

                // ###BEGIN###{Look-ISDU}
                x += '<td style=width:24px><img src=images-isdu/ComputerIcon.png style=padding-top:2px /></td>';
                // ###END###{Look-ISDU}
                // ###BEGIN###{Look-Commander}
                //x += '<td class=j' + (computer['icon'] ? computer['icon'] : 1) + '></td>';
                // ###END###{Look-Commander}
                // ###BEGIN###{Look-BrandedCommander}
                x += '<td><img src=images-BrandedCommander/ComputerIcon.png style=vertical-align:text-top /></td>';
                // ###END###{Look-BrandedCommander}
                // ###BEGIN###{Scripting}
                x += '<td style=width:10px><input id=SJ-' + computer['h'] + ' type=checkbox onclick=onComputerChecked()' + (computer.checked?' checked':'') + (computersRunningScripts>0?' disabled':'') + ' /></td>';
                // ###END###{Scripting}

                x += '<td align=left><b style=font-size:16px>' + EscapeHtml(name) + '</b></td>';

                // ###BEGIN###{!Scripting}
                // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td>';
                // ###END###{ComputerSelector-Local-ScriptOnly}
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td><td style=width:1px;padding-right:5px>' + AddButton2("Collegare", 'computerConnect(event,' + computer['h'] + ')', disabled ? 'disabled=disabled' : '') + '</td>';
                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###END###{!Scripting}
                // ###BEGIN###{Scripting}
                if (computersRunningScripts == 0) {
                    // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                    x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td>';
                    // ###END###{ComputerSelector-Local-ScriptOnly}
                    // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                    x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td><td style=width:1px;padding-right:5px>' + AddButton2("Collegare", 'computerConnect(event,' + computer['h'] + ')', disabled?'disabled=disabled':'') + '</td>';
                    // ###END###{!ComputerSelector-Local-ScriptOnly}
                } else {
                    if (computer.scriptstate) { x += '<td align=right style=padding-right:5px id=XI-' + computer['h'] + '>' + EscapeHtml(computer['consolemsg']) + '</td><td style=width:1px>' + AddButton2("Fermare", 'computerStopScript(event,' + computer['h'] + ')') + '</td>'; }
                }
                // ###END###{Scripting}

                x += '<td id=RCX-' + computer['h'] + ' class=g2 style=float:none>&nbsp;</td>' // Right side gray scale
                x += '</table></div></div>';

                groupHtml[group] += x; // Add this device to the proper group
            }

            // Append all the groups into the final HTML
            if (computerlist.length > 0) {
                var x = '';
                for (var y in groups) {
                    if (groups[y] != '') { x += '<div style="font-size:14px;border-bottom:1px solid lightgray;margin-left:4px;margin-top:6px"><b>' + EscapeHtml(groups[y]) + '</b></div>'; }
                    x += groupHtml[groups[y]];
                }
                QH('id_computerList', '<div style=width:99%>' + x + '</div>');
            }
            updateComputerDetails();
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }

        function onComputerChecked() {
            for (var y in computerlist) { computerlist[y].checked = Q('SJ-' + computerlist[y]['h']).checked; }
        }

        function addComputerDetailsEntry(x, y) {
            //return '<div class=log style=border-radius:4px;padding:3px;margin-bottom:3px><div style=width:100%;font-size:9px>' + x + '</div><div style=width:100%>&nbsp;' + y + '</div></div>';
            return '<div style=border-radius:4px;padding:3px;margin-bottom:3px;background-color:#ddd><div style=width:100%;font-size:9px>' + x + '</div><div style=width:100%>&nbsp;' + y + '</div></div>';
        }

        function updateComputerDetails() {
            var x = '<div style=position:absolute;top:0;right:0;left:0;bottom:0>', disabled = false;
            if (currentcomputer != null) {
                // ###BEGIN###{Look-Commander}
                // Put the big computer logo
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div style=position:absolute;top:4px;left:4px;right:4px;bottom:80px>';
                if (currentcomputer['name']) x += '<div style=width:100%;text-align:center><b>' + EscapeHtml(decodeURIComponent(currentcomputer['name'])) + '</b></div>';
                // ###BEGIN###{ComputerSelectorScanner}
                var icon = 1, gray = false;
                if ((NW_AmtScanMenuItem) && (NW_AmtScanMenuItem.checked == true)) { gray = (!globalAmtScanner.scanTable[currentcomputer['h']]) || (globalAmtScanner.scanTable[currentcomputer['h']].scanstate != 1); }
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) { disabled = gray = ((currentcomputer.conn & 14) == 0); }
                // ###END###{MeshServerConnect}
                if (currentcomputer['icon']) { icon = parseInt(currentcomputer['icon']); }
                x += '<img ' + (gray ? 'class=gray ' : '') + 'src="images-commander/icons200-' + icon + '-1.png" onclick=showIconSelector() height=200 width=200 style=margin-left:50px;cursor:pointer></img>';
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{!ComputerSelectorScanner}
                var icon = 1;
                if (currentcomputer['icon']) { icon = parseInt(currentcomputer['icon']); }
                x += '<img src="images-commander/icons200-' + icon + '-1.png" onclick=showIconSelector() height=200 width=200 style=margin-left:50px;cursor:pointer></img>';
                // ###END###{!ComputerSelectorScanner}
                // ###END###{!ComputerSelectorNoImages}

                x += '</div>';
                // ###END###{Look-Commander}

                var bottomButtons = '';
                var bottomButtonsHeight = 0;
                if (computersRunningScripts == 0) {
                    //bottomButtons += '<div style=position:fixed;bottom:8px;right:5px>';
                    bottomButtonsHeight = 14 + 20;
                    bottomButtons += '<div style=position:absolute;bottom:8px;left:4px;right:4px>';
                    // ###BEGIN###{Scripting}
                    if (currentcomputer['consolemsgs']) { bottomButtonsHeight += 20; bottomButtons += '<input type=Button value="' + "Mostra output script ..." + '" style=width:292px onclick=mscript_showComputerScriptOutput(' + currentcomputer['h'] + ')><br>'; }
                    // ###END###{Scripting}
                    // ###BEGIN###{ComputerSelector-Local}
                    // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                    bottomButtons += '<input type=Button value="' + "Modificare..." + '" style=width:146px onclick=computerEdit(' + currentcomputer['h'] + ')>';
                    bottomButtons += '<input type=Button value="' + "Collegare" + '" style=width:146px onclick=computerConnect(event,' + currentcomputer['h'] + ') ' + (disabled ? 'disabled=disabled' : '') + '>';
                    // ###END###{!ComputerSelector-Local-ScriptOnly}
                    // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                    bottomButtons += '<input type=Button value="' + "Modificare..." + '" style=width:292px onclick=computerEdit(' + currentcomputer['h'] + ')>';
                    // ###END###{ComputerSelector-Local-ScriptOnly}
                    // ###END###{ComputerSelector-Local}
                    // ###BEGIN###{!ComputerSelector-Local}
                    // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                    bottomButtons += '<input type=Button value="' + "Collegare" + '" style=width:292px onclick=computerConnect(event,' + currentcomputer['h'] + ' ' + (disabled ? 'disabled=disabled' : '') + ')>';
                    // ###END###{!ComputerSelector-Local-ScriptOnly}
                    // ###END###{!ComputerSelector-Local}
                    bottomButtons += '</div>';
                } else {
                    // ###BEGIN###{Scripting}
                    if (currentcomputer.scriptstate || currentcomputer['consolemsgs']) {
                        //bottomButtons += '<div style=position:fixed;bottom:8px;right:5px>';
                        bottomButtonsHeight = 14;
                        bottomButtons += '<div style=position:absolute;bottom:8px;left:4px;right:4px>';
                        if (currentcomputer['consolemsgs'] != null) { bottomButtonsHeight += 20; bottomButtons += '<input type=Button value="' + "Mostra output script ..." + '" style=width:292px onclick=mscript_showComputerScriptOutput(' + currentcomputer['h'] + ')><br>'; }
                        if (currentcomputer.scriptstate != null) { bottomButtonsHeight += 20; bottomButtons += '<input type=Button value="' + "Stop Script" + '" style=width:292px onclick=computerStopScript(event,' + currentcomputer['h'] + ')>'; }
                        bottomButtons += '</div>';
                    }
                    // ###END###{Scripting}
                }

                // ###BEGIN###{Look-Commander}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div style="overflow-y:auto;position:absolute;top:216px;left:4px;right:4px;bottom:' + bottomButtonsHeight + 'px">';
                // ###END###{!ComputerSelectorNoImages}
                // ###BEGIN###{ComputerSelectorNoImages}
                x += '<div style="overflow-y:auto;position:absolute;top:4px;left:4px;right:4px;bottom:' + bottomButtonsHeight + 'px">';
                // ###END###{ComputerSelectorNoImages}
                // ###END###{Look-Commander}
                // ###BEGIN###{!Look-Commander}
                x += '<div style="overflow-y:auto;position:absolute;top:4px;left:4px;right:4px;bottom:' + bottomButtonsHeight + 'px">';
                if (currentcomputer['name']) x += addComputerDetailsEntry("Nome amichevole", EscapeHtml(decodeURIComponent(currentcomputer['name'])));
                // ###END###{!Look-Commander}
                x += addComputerDetailsEntry("Nome host", decodeURIComponent(currentcomputer['host']));

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer == null) {
                // ###END###{MeshServerConnect}
                if (currentcomputer['user'] != '*') {
                    x += addComputerDetailsEntry("Autenticazione", "Digerire /" + EscapeHtml(decodeURIComponent(currentcomputer['user'])));
                } else {
                    if (currentcomputer['pass'] == '') {
                        x += addComputerDetailsEntry("Autenticazione", "Kerberos");
                    } else {
                        x += addComputerDetailsEntry("Autenticazione", "Kerberos /" + EscapeHtml(decodeURIComponent(currentcomputer['pass'])));
                    }
                }
                x += addComputerDetailsEntry("Sicurezza", ((currentcomputer['tls'] == 0)?"Nessuna":"Sicurezza TLS"));
                if (currentcomputer['tags']) { x += addComputerDetailsEntry("Nome del gruppo", EscapeHtml(decodeURIComponent(currentcomputer['tags']))); }
                // ###BEGIN###{MeshServerConnect}
                } else {
                    if (currentcomputer['tags']) { x += addComputerDetailsEntry("Gruppo di dispositivi", EscapeHtml(decodeURIComponent(currentcomputer['tags']))); }
                    if (currentcomputer['conn']) {
                        var cn = [];
                        if ((currentcomputer['conn'] & 1) != 0) cn.push('Agent');
                        if ((currentcomputer['conn'] & 2) != 0) cn.push('CIRA');
                        else if ((currentcomputer['conn'] & 4) != 0) cn.push('Direct');
                        else if ((currentcomputer['conn'] & 8) != 0) cn.push('Relay');
                        x += addComputerDetailsEntry("Connettività", cn.join(', '));
                    }
                }
                // ###END###{MeshServerConnect}

                if (currentcomputer['ver']) {
                    var mode = '';
                    if (currentcomputer['pstate'] == 2) { mode = "ACM"; if (currentcomputer['pmode'] == 2) mode = "CCM"; }
                    if (mode != '') mode = ' / ' + mode;
                    x += addComputerDetailsEntry("Intel&reg; AMT", "v" + currentcomputer['ver'] + mode);
                }
                if (currentcomputer['date']) { x += addComputerDetailsEntry("Ultima connessione", new Date(currentcomputer['date']).toDateString()); }
                if (currentcomputer['digestrealm']) {
                    // ###BEGIN###{ContextMenus}
                    x += '<div cm="' + NoBreak("Rimuovi regno ...") + '#removeCurrentRealm(' + currentcomputer['h'] + ')">';
                    // ###END###{ContextMenus}
                    x += addComputerDetailsEntry("Digest Realm", '<span style=font-size:x-small>' + currentcomputer['digestrealm'] + '</span><br /><span style=margin-left:5px><a style=cursor:pointer;font-size:10px;color:blue onclick=removeCurrentRealm(' + currentcomputer['h'] + ')><u>' + "Rimuovi regno" + '</u></a></span>');
                    // ###BEGIN###{ContextMenus}
                    x += '</div>';
                    // ###END###{ContextMenus}
                }
                // ###BEGIN###{Mode-NodeWebkit}
                // ###BEGIN###{Certificates}
                if (currentcomputer['tlscerthash']) {
                    if (currentcomputer['tlscert']) {
                        // ###BEGIN###{ContextMenus}
                        x += '<div cm="' + NoBreak("Visualizza certificato...") + '#viewCurrentPinCertificate(' + currentcomputer['h'] + ')|' + NoBreak("Rimuovi pinning ...") + '#removeCurrentPinCertificate(' + currentcomputer['h'] + ')">';
                        // ###END###{ContextMenus}
                        x += addComputerDetailsEntry("Certificato TLS", '<span title="Cert hash: ' + currentcomputer['tlscerthash'] + '">' + "Appuntato a un certificato specifico" + '</span><br /><span style=margin-left:5px><a style=cursor:pointer;font-size:10px;color:blue onclick=viewCurrentPinCertificate(' + currentcomputer['h'] + ')><u>' + "Mostra certificato" + '</u></a> <a style=cursor:pointer;font-size:10px;color:blue onclick=removeCurrentPinCertificate(' + currentcomputer['h'] + ')><u>' + "Rimuovi pinning" + '</u></a></span>');
                        // ###BEGIN###{ContextMenus}
                        x += '</div>';
                        // ###END###{ContextMenus}
                    } else {
                        // ###BEGIN###{ContextMenus}
                        x += '<div cm="' + NoBreak("Rimuovi pinning ...") + '#removeCurrentPinCertificate(' + currentcomputer['h'] + ')">';
                        // ###END###{ContextMenus}
                        x += addComputerDetailsEntry("Certificato TLS", '<span title="Cert hash: ' + currentcomputer['tlscerthash'] + '">' + "Appuntato a un certificato specifico" + '</span><br /><span style=margin-left:5px><a style=cursor:pointer;font-size:10px;color:blue onclick=removeCurrentPinCertificate(' + currentcomputer['h'] + ')><u>' + "Rimuovi pinning" + '</u></a></span>');
                        // ###BEGIN###{ContextMenus}
                        x += '</div>';
                        // ###END###{ContextMenus}
                    }
                }
                // ###END###{Certificates}
                // ###END###{Mode-NodeWebkit}
                x += '</div>';

            }
            QH('id_computerDetails', x + bottomButtons + '</div>');
            computerSelect();
        }

        // ###BEGIN###{Look-Commander}
        // ###BEGIN###{!ComputerSelectorNoImages}
        function showIconSelector() {
            if (xxdialogMode) return;
            var x = '<br><div style=display:inline-block;width:40px></div>';
            x += '<div style=display:inline-block class=i1 onclick=setIcon(1)></div>';
            x += '<div style=display:inline-block class=i2 onclick=setIcon(2)></div>';
            x += '<div style=display:inline-block class=i3 onclick=setIcon(3)></div>';
            x += '<div style=display:inline-block class=i4 onclick=setIcon(4)></div>';
            x += '<div style=display:inline-block class=i5 onclick=setIcon(5)></div>';
            x += '<div style=display:inline-block class=i6 onclick=setIcon(6)></div>';
            setDialogMode(11, "Selezione dell'icona", 0, null, x);
            QV('id_dialogclose', true);
        }

        function setIcon(icon) {
            setDialogMode(0);
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) { meshCentralServer.send({ action: 'changedevice', nodeid: currentcomputer._id, icon: icon }); return; }
            // ###END###{MeshServerConnect}
            currentcomputer['icon'] = icon;
            // ###BEGIN###{ComputerSelector-Local}
            saveComputers();
            // ###END###{ComputerSelector-Local}
            updateComputerList();
        }
        // ###END###{!ComputerSelectorNoImages}
        // ###END###{Look-Commander}

        // ###BEGIN###{Mode-NodeWebkit}
        // ###BEGIN###{ContextMenus}
        // ###BEGIN###{Certificates}
        function viewCurrentPinCertificate(h) {
            if (xxdialogMode) return;
            var c = null;
            for (var x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            var cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(hex2rstr(c['tlscert'])));
            var commonName = cert.subject.getField('CN').value;
            var fingerprint = '', fingerprint2 = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex().toUpperCase();
            for (i = 0; i < fingerprint2.length; i++) { if ((i != 0) && (i % 2 == 0)) { fingerprint += ':'; } fingerprint += fingerprint2.substring(i, i + 1); }
            var x = '<img src=images-commander/cert1.png style=float:right height=32 width=32 />';
            x += 'This certificate is pinned to computer ' + c['name'] + '. When connecting, if this certificate is received the connection will allowed. Hit delete button to un-pin.<br>';
            // ###BEGIN###{FileSaver}
            //x += addHtmlValue("Certificate", c.X509Certificate.length + " bytes, " + '<a style=cursor:pointer;color:blue onclick=downloadCert(' + h + ')>' + "Download" + '</a>');
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            //x += addHtmlValue("Certificate", c.X509Certificate.length + " bytes");
            // ###END###{!FileSaver}
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Oggetto del certificato" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.subject.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            x += addHtmlValueNoTitle("impronta digitale", fingerprint.substring(0,29) + '<br />' + fingerprint.substring(30));
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificato dell'Emittente" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.issuer.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            setDialogMode(11, "Certificato -" + EscapeHtml(commonName), 5, function (b) { if (b == 2) { removeCurrentPinCertificateEx(2, h); } }, x);
        }

        function removeCurrentPinCertificate(h) {
            if (xxdialogMode) return;
            setDialogMode(11, "Appuntamento del certificato", 3, removeCurrentPinCertificateEx, "Rimuovere l'appuntamento del certificato per il computer selezionato?", h);
        }

        function removeCurrentPinCertificateEx(button, h) {
            var c = null;
            for (var x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            if (c['tlscert']) delete c['tlscert'];
            if (c['tlscerthash']) delete c['tlscerthash'];
            storeCertPinning(c['host'], null);
            saveComputers();
            updateComputerList();
        }
        // ###END###{Certificates}
        // ###END###{ContextMenus}
        // ###END###{Mode-NodeWebkit}

        function removeCurrentRealm(h) {
            if (xxdialogMode) return;
            setDialogMode(11, "Digest Realm", 3, removeCurrentRealmEx, "Rimuovere il pin Digest Realm per il computer selezionato?", h);
        }

        function removeCurrentRealmEx(button, h) {
            var c = null;
            for (var x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            if (c['digestrealm']) delete c['digestrealm'];
            saveComputers();
            updateComputerList();
        }

        // ###BEGIN###{ComputerSelector-Local}
        function saveComputers() {
            if (urlvars['host']) return;
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) return;
            // ###END###{MeshServerConnect}
            // ###BEGIN###{Mode-NodeWebkit}
            const crypto = require('crypto');
            crypto.randomBytes(256, function(err, buf) {
                if (err) throw err; // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                var computerlist2 = JSON.parse(JSON.stringify(computerlist));
                for (var i in computerlist2) { delete computerlist2[i]['tlscert2']; delete computerlist2[i]['tlscerthash2']; } // Clean up the list
                var k = buf.toString('hex'), cipher = crypto.createCipher('aes-256-ctr', k), crypted = cipher.update(JSON.stringify(computerlist2), 'utf8', 'hex');
                crypted += cipher.final('hex');
                try { localStorage.setItem('computers', k + crypted); } catch (ex) { }
            });
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            try { localStorage.setItem('computers', JSON.stringify(computerlist)); } catch (ex) { }
            // ###END###{!Mode-NodeWebkit}
        }

        function loadComputers() {
            if (urlvars['host']) return;
            // ###BEGIN###{Mode-NodeWebkit}
            var ctext = null;
            try { ctext = localStorage.getItem('computers'); } catch (ex) { }
            if (ctext) {
                try { computerlist = JSON.parse(ctext); } catch (e) {
                    if (ctext.length > 512) { // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                        var crypto = require('crypto'), k = ctext.substring(0, 512), crypted = ctext.substring(512), decipher = crypto.createDecipher('aes-256-ctr', k), dec = decipher.update(crypted, 'hex', 'utf8');
                        dec += decipher.final('utf8');
                        try { computerlist = JSON.parse(dec); } catch (e) { computerlist = []; }
                        var pins = getCertPinnings();
                        for (var i in computerlist) {
                            computerlist[i].checked = false;
                            // Add stored certificate pinning.
                            if ((computerlist[i]['tlscerthash'] == null) && (pins[computerlist[i]['host']] != null)) { computerlist[i]['tlscerthash'] = pins[computerlist[i]['host']]; }
                            delete computerlist[i]['tlscert2'];
                            delete computerlist[i]['tlscerthash2'];
                        }
                    }
                }
            }
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            var ctext = null;
            try { ctext = localStorage.getItem('computers'); } catch (ex) { }
            if (ctext) { try { computerlist = JSON.parse(ctext); } catch (e) { computerlist = []; } }
            // ###END###{!Mode-NodeWebkit}
            updateComputerList();
            // ###BEGIN###{ComputerSelectorScanner}
            // ###BEGIN###{Mode-NodeWebkit}
            globalAmtScanner.performScan();
            // ###END###{Mode-NodeWebkit}
            // ###END###{ComputerSelectorScanner}
        }
        // ###END###{ComputerSelector-Local}

        function computerConnect(e, h, m, skipPass) {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            if ((m == 100) || (e && (e.shiftKey == true))) {
                // Launch a new instance of MeshCommander
                var adder = '';
                // ###BEGIN###{Desktop}
                if (m == 1) { adder = '&kvm=1'; }
                if (m == 2) { adder = '&kvmfull=1'; }
                if (m == 3) { adder = '&kvmonly=1'; }
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (m == 4) { adder = '&sol=1'; }
                // ###END###{Terminal}
                var username = currentcomputer['user'];
                if (username == '') { username = 'admin'; }
                require('nw.gui').Window.open(window.location.href + '?host=' + currentcomputer['host'] + '&user=' + username + '&pass=' + currentcomputer['pass'] + '&tls=' + currentcomputer['tls'] + adder, { 'icon': 'favicon.png', 'toolbar': false, 'frame': true, 'width': 970, 'min_width': 970, 'height': 760, 'min_height': 640 });
                //require('child_process').exec('nw.exe -host:' + decodeURIComponent(currentcomputer['host']) + ' -user:' + decodeURIComponent(currentcomputer['user']) + ' -pass:' + decodeURIComponent(currentcomputer['pass']) + ((currentcomputer['tls']==1)?' -tls':''), function (error, stdout, stderr) { });
                return;
            }
            // ###END###{Mode-NodeWebkit}
            if (e) haltEvent(e);
            computerSelect(null, h);
            if (currentcomputer == null) return;
            if ((currentcomputer['user'] != '*') && (currentcomputer['pass'] == '')) {
                if (skipPass === true) { computerConnectLogin(9, m); return; }
                // Query for the login password
                var x = '<br>Enter the login password for ' + EscapeHtml(currentcomputer['name'] ? currentcomputer['name'] : currentcomputer['host']) + '.<br><br>';
                x += '<div style=height:26px><input id=d11connectUser onkeyup=computerConnectUpdateLogin() style=float:right;width:200px value="' + currentcomputer['user'] + '"><div>' + "Nome utente" + '</div></div>';
                x += '<div style=height:26px><input id=d11connectPass onkeyup=computerConnectUpdateLogin(event) type=password style=float:right;width:200px><div>' + "Parola d'ordine" + '</div></div>';
                setDialogMode(11, "Credenziali di accesso", 3, computerConnectLogin, x);
                Q('d11connectPass').focus();
                computerConnectUpdateLogin();
            } else {
                // Go ahead and connect
                computerConnectLogin(0, m);
            }
        }

        function computerConnectUpdateLogin(e) {
            var ok = (Q('d11connectUser').value.length > 0) && (passwordcheck(Q('d11connectPass').value));
            QE('idx_dlgOkButton', ok);
            if ((e != undefined) && (e.keyCode == 13) && (ok == true)) { setDialogMode(0); computerConnectLogin(1, xxdialogTag); }
        }

        // If the user is prompted for a user/pass, we should not re-prompt after a certificate validation prompt.
        var skipPassUser = null;
        var skipPassPass = null;
        function computerConnectLogin(button, m) {
            var user = decodeURIComponent(currentcomputer['user']);
            var pass = decodeURIComponent(currentcomputer['pass']);
            if (button == 1) { user = Q('d11connectUser').value; pass = Q('d11connectPass').value; }
            if (button == 9) { user = skipPassUser; pass = skipPassPass; }
            skipPassUser = user;
            skipPassPass = pass;

            // Go ahead and connect
            var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
            if (user == '') { user = 'admin'; } // Default to admin if not specified.
            connect(ports.host, ports.http, user, pass, currentcomputer['tls'], function (mtag) {
                // ###BEGIN###{Mode-NodeWebkit}
                // If the fingerprint is set but not the certificate, set the cert.
                if (wsstack.comm.xtlsCertificate && (currentcomputer['tlscert'] == null) && (wsstack.comm.xtlsFingerprint == currentcomputer['tlscerthash'])) {
                    currentcomputer['tlscert'] = wsstack.comm.xtlsCertificate.raw.toString('hex');
                    updateComputerDetails();
                }
                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{Desktop}
                if (mtag == 1) { go(14); connectDesktop(); } // Go directly to remote desktop (1)
                if ((mtag == 2) || (mtag == 3)) { connectDesktop(); } // Go remote desktop fullscreen (2) and only remote desktop (3)
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (mtag == 4) { go(13); connectTerminal(); } // Go directly to terminal (4)
                // ###END###{Terminal}
            }, m);
            if (m == 1) { go(14); }
            if ((m == 2) || (m == 3)) { go(14); deskToggleFull(m == 3); }
            if (m == 4) { go(13); }
        }

        function computerSelect(e, h) {
            if (h && ((currentcomputer == null) || (currentcomputer.h !== h))) { currentcomputer = getComputer(h); updateComputerDetails(); }
            for (var y in computerlist) {
                var computer = computerlist[y], sel = (currentcomputer != null && computer['h'] == currentcomputer['h']);
                QS('CI-' + computer['h'])['background-color'] = sel ? '#a0a0a0' : '#c9c9c9';
                Q('LCX-' + computer['h']).classList.remove('g1');
                Q('LCX-' + computer['h']).classList.remove('g1s');
                Q('RCX-' + computer['h']).classList.remove('g2');
                Q('RCX-' + computer['h']).classList.remove('g2s');
                Q('LCX-' + computer['h']).classList.add(sel?'g1s':'g1');
                Q('RCX-' + computer['h']).classList.add(sel?'g2s':'g2');
            }
        }

        function getComputer(h) { for (var i in computerlist) { if (computerlist[i]['h'] == h) return computerlist[i]; } return null; }

        // ###BEGIN###{Scripting}
        function mscript_showComputerScriptOutput(h) {
            if (xxdialogMode) return;
            var computer = getComputer(h);
            computer.consoledialog = 'scriptOutputArea';
            var name = computer['name'];
            if (!name) name = computer['host'];
            var v = '<textarea id=scriptOutputArea style=width:100%;height:150px;resize:vertical spellcheck=false readonly></textarea>';
            setDialogMode(11, "Output dello script -" + name, 5, mscript_showComputerScriptOutputOk, v, computer);
            Q('scriptOutputArea').value = EscapeHtml(computer['consolemsgs']);
        }

        function mscript_showComputerScriptOutputOk(button, computer) {
            computer.consoledialog = undefined;
            if (button == 2) {
                if (computer.scriptstate) {
                    computer['consolemsgs'] = '';
                } else {
                    delete computer['consolemsgs'];
                    delete computer['consolemsg'];
                }
                saveComputers();
                updateComputerDetails();
            }
        }

        function mscript_runScriptDlg() {
            if (computersRunningScripts > 0) {
                // Stop all scripts
                for (var y in computerlist) {
                    var computer = computerlist[y];
                    if (computer.scriptstate) { computer.scriptstate.stop(); computer.scriptstate = undefined; }
                }
                updateComputerList();
            } else {
                // Start a new script dialog box
                if (xxdialogMode || scriptstate) return;
                var clist = [];
                for (var y in computerlist) { if (computerlist[y].checked == true) { clist.push(computerlist[y]); } }
                if (clist.length == 0) { clist.push(currentcomputer); }
                setDialogMode(11, "Esegui script", 3, mscript_runScriptDlgOk, '<br>' + format("Esegui uno script selezionato su {0} computer", clist.length) + '.<br><br><input id=mscriptopen type=file style=width:100% accept=".mescript">');
            }
        }

        function mscript_runScriptDlgOk(r) {
            if (r != 1) return;
            var x = Q('mscriptopen');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = mscript_onScriptReadNoPrompt;
            reader.readAsBinaryString(x.files[0]);
        }

        function mscript_onScriptReadNoPrompt(file) { mscript_onScriptRead(file, 1); }
        function mscript_onScriptRead(file, noprompt) {
            if (computersRunningScripts > 0) return;
            var x, clist = [];
            try { x = JSON.parse(file.target.result); } catch (e) {}
            if (x && x['mescript']) {
                onComputerChecked();
                for (var y in computerlist) { if (computerlist[y].checked == true) { clist.push(computerlist[y]); } }
                if (clist.length == 0) { clist.push(currentcomputer); }
                x.clist = clist;
                if (noprompt == 1) {
                    mscript_onScriptReadOk(0, x);
                } else {
                    setDialogMode(11, "Esegui script", 3, mscript_onScriptReadOk, format("Eseguire questo script su {0} computer?", clist.length), x);
                }
            }
        }

        function mscript_onScriptReadOk(button, tag) {
            var x = tag;

            // ###BEGIN###{CertificateManager}
            var tlsoptions = {};

            // Create a list of trusted certificates in PEM format
            var trustedCertStringsPem = [];
            for (var y in certificateStore) {
                var certificate = certificateStore[y];
                if (certificate['trusted'] == true) { trustedCertStringsPem.push('-----BEGIN CERTIFICATE-----\n' + certificate['certbin'] + '\n-----END CERTIFICATE-----\n'); }
            }
            tlsoptions.ca = trustedCertStringsPem;

            // Setup out console TLS authentication certificate
            var authcert = getTlsAuthCertificate();
            if (authcert != null) {
                tlsoptions.cert = forge.pki.certificateToPem(authcert['cert']);
                tlsoptions.key = forge.pki.privateKeyToPem(authcert['privateKey']);
            }
            // ###END###{CertificateManager}

            for (var y in x.clist) {
                var mscriptstate, computer = x.clist[y], startvars = { '_interactive':0 };
                // ###BEGIN###{Certificates}
                startvars['_certificates'] = 1;
                // ###END###{Certificates}
                // ###BEGIN###{Mode-Firmware}
                startvars['_mode'] = 'Firmware';
                // ###END###{Mode-Firmware}
                // ###BEGIN###{Mode-MeshCentral2}
                startvars['_mode'] = 'MeshCentral2';
                // ###END###{Mode-MeshCentral2}
                // ###BEGIN###{Mode-NodeWebkit}
                startvars['_mode'] = 'NodeWebkit';
                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{Mode-LMS}
                startvars['_mode'] = 'LMS';
                // ###END###{Mode-LMS}
                // ###BEGIN###{Mode-WebSite}
                startvars['_mode'] = 'WebSite';
                // ###END###{Mode-WebSite}
                if (x && x['mescript']) mscriptstate = script_setup(atob(x['mescript']), startvars);
                if (mscriptstate) {
                    mscriptstate.computer = computer;
                    var ports = portsFromHost(computer['host'], computer['tls']);
                    // ###BEGIN###{CertificateManager}
                    mscriptstate.wsstack = WsmanStackCreateService(ports.host, ports.http, decodeURIComponent(computer['user']), decodeURIComponent(computer['pass']), computer['tls'], tlsoptions);
                    // ###END###{CertificateManager}
                    // ###BEGIN###{!CertificateManager}
                    mscriptstate.wsstack = WsmanStackCreateService(ports.host, ports.http, decodeURIComponent(computer['user']), decodeURIComponent(computer['pass']), computer['tls']);
                    // ###END###{!CertificateManager}
                    mscriptstate.amtstack = AmtStackCreateService(mscriptstate.wsstack);
                    mscriptstate.onStep = mscript_updateScriptState;
                    mscriptstate.onConsole = mscript_console;

                    // Setup TLS checking
                    // ###BEGIN###{Mode-NodeWebkit}
                    if (NW_TlsSecurityMode == 0) { mscriptstate.wsstack.comm.xtlsFingerprint = 0; }
                    else { mscriptstate.wsstack.comm.xtlsFingerprint = computer['tlscerthash'] ? computer['tlscerthash'] : computer['tlscerthash2']; }
                    // ###END###{Mode-NodeWebkit}

                    computer['consolemsg'] = '';
                    computer['consolemsgs'] = '';
                    computer.scriptstate = mscriptstate;
                    computer.scriptstate.start(100);
                } else {
                    messagebox("Esegui script", "File di script non valido.")
                    return;
                }
            }
            updateComputerList();
        }

        function mscript_updateScriptState(scriptstate) {
            if (scriptstate.state == 0) { scriptstate.computer.scriptstate = undefined; updateComputerList(); }
        }

        function mscript_console(msg, scriptstate) {
            scriptstate.computer['consolemsg'] = msg;
            scriptstate.computer['consolemsgs'] += (msg + '\r\n');
            if (scriptstate.computer.consoledialog) { Q(scriptstate.computer.consoledialog).value = scriptstate.computer['consolemsgs']; }
            QH('XI-' + scriptstate.computer['h'], msg);
        }

        function computerStopScript(e, h) {
            var computer = getComputer(h);
            if (computer.scriptstate) { computer.scriptstate.stop(); computer.scriptstate = undefined; }
            updateComputerList();
        }

        // ###END###{Scripting}

        //
        // MeshCentral Connection
        //
        // ###BEGIN###{MeshServerConnect}
        function showMeshCentralConnectDialog(showtoken) {
            if (xxdialogMode || meshCentralServer) return;
            var x = '<img src=\'images-commander/meshcentral50.png\' style=width:50px;height:50px;float:right></img><div>' + "Connect to a MeshCentral server and manage Intel&reg; AMT computers on that account." + '<div><br style=clear:both />';
            x += '<div style=height:26px><input id=meshserverurl value="" placeholder="sample.server.com:443" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Nome del server" + '</div></div>';
            x += '<div style=height:26px><input id=meshserverhash value="" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Hash certificato" + '</div></div>';
            x += '<div style=height:26px><input id=meshserveruser value="" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Nome utente" + '</div></div>';
            x += '<div style=height:26px><input id=meshserverpass value="" type=password style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Parola d'ordine" + '</div></div>';
            if (showtoken) { x += '<div style=height:26px><input id=meshservertoken value="" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Token di accesso" + '</div></div>'; }
            //x += '<div style=height:26px><input id=meshserverproxy value="" placeholder="proxy.com:123" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Proxy" + '</div></div>';
            setDialogMode(11, "MeshCentral Connect", 3, showMeshCentralConnectDialogOk, x);
            try {
                if (localStorage.getItem('meshserverurl')) { Q('meshserverurl').value = localStorage.getItem('meshserverurl'); }
                if (localStorage.getItem('meshserverhash')) { Q('meshserverhash').value = localStorage.getItem('meshserverhash'); }
                if (localStorage.getItem('meshserveruser')) { Q('meshserveruser').value = localStorage.getItem('meshserveruser'); }
                //if (localStorage.getItem('meshserverproxy')) { Q('meshserverproxy').value = localStorage.getItem('meshserverproxy'); }
            } catch (ex) { }
            showMeshCentralConnectDialogUpdate();
        }

        function showMeshCentralConnectDialogUpdate() {
            QS('meshserverurl')['background-color'] = ((Q('meshserverurl').value.length > 0) ? 'white' : 'LightYellow');
            QS('meshserveruser')['background-color'] = ((Q('meshserveruser').value.length > 0) ? 'white' : 'LightYellow');
            QS('meshserverpass')['background-color'] = ((Q('meshserverpass').value.length > 0) ? 'white' : 'LightYellow');
            var token = true;
            try { token = (Q('meshservertoken').value.length > 0); } catch (ex) { }
            QE('idx_dlgOkButton', token && (Q('meshserverurl').value.length > 0) && (Q('meshserveruser').value.length > 0) && (Q('meshserverpass').value.length > 0));
        }

        function showMeshCentralConnectDialogOk() {
            try {
                localStorage.setItem('meshserverurl', Q('meshserverurl').value);
                localStorage.setItem('meshserverhash', Q('meshserverhash').value);
                localStorage.setItem('meshserveruser', Q('meshserveruser').value);
            } catch (ex) { }
            var pass = Q('meshserverpass').value;
            var token = null;
            try { token = Q('meshservertoken').value; } catch (ex) { }
            //try { localStorage.setItem('meshserverproxy', Q('meshserverproxy').value); } catch (ex) { }
            var serverUrl = Q('meshserverurl').value;
            if (serverUrl.indexOf('://') < 0) { serverUrl = ('wss://' + serverUrl); }
            serverUrl = new URL(serverUrl);
            var serverPort = parseInt(serverUrl.port);
            if (isNaN(serverPort) || serverPort == 0) { serverPort = 443; }
            meshCentralServer = CreateMeshCentralServer(serverUrl.hostname, serverPort, '/control.ashx', Q('meshserveruser').value, Q('meshserverpass').value, token, Q('meshserverhash').value);
            meshCentralServer.onStateChange = function (sender, state, cause, msg) {
                var askForToken = false;
                if (state == 0) {
                    // Disconnected
                    loadComputers();
                    // If the connection failed due to hash mismatch, prompt the user.
                    disconnect();
                    QH('id_computername', format("Console di gestione remota v{0}", version));
                    if (cause == 'HashMatchFail') { showTlsCert(3, "Connesso al server MeshCentral con certificato non riconosciuto. Fare clic su OK per accettare e connettersi.", meshCentralServer.xtlsCertificate, meshCentralServer.password, meshCentralHashRetry); }
                    else if ((cause == 'noauth') && (msg == 'tokenrequired')) { askForToken = true; }
                    else if (cause == 'noauth') { setDialogMode(11, "Connessione MeshCentral", 1, null, "Nome utente o password errati."); }
                    meshCentralServer = null;
                } else if (state == 1) {
                    // Connecting
                    currentcomputer = null;
                    computerlist = [];
                    QH('id_computername', 'Remote Management Console v' + version + ', Connecting to ' + meshCentralServer.host + '...');
                } else if (state == 3) {
                    // Connected
                    currentcomputer = null;
                    computerlist = meshCentralServer.computerlist;
                    meshCentralServer.xconnected = true;
                    QH('id_computername', 'Remote Management Console v' + version + ', Server: ' + meshCentralServer.host);
                }
                updateComputerList();
                NW_SetupMainMenu(currentView);

                if (askForToken) {
                    // Ask for 2-factor token and try again
                    showMeshCentralConnectDialog(true);
                    Q('meshserverpass').value = pass;
                    Q('meshservertoken').focus();
                    showMeshCentralConnectDialogUpdate();
                }
            }
            meshCentralServer.onNodeChange = function (sender, node) {
                //computerlist = meshCentralServer.computerlist;
                updateComputerList();
            }
            setDialogMode(0);
            meshCentralServer.connect();
        }

        // The user accepted the MeshCentral server hash, set it and try to connect again.
        function meshCentralHashRetry(b, args) {
            try { localStorage.setItem('meshserverhash', args.c.fingerprint.split(':').join('').toLowerCase()); } catch (ex) { }
            showMeshCentralConnectDialog();
            Q('meshserverpass').value = args.m; // Set the retry password
            showMeshCentralConnectDialogOk();
        }

        function meshCentralDisconnect() {
            if (meshCentralServer == null) return;
            meshCentralServer.disconnect();
            meshCentralServer = null;
            currentcomputer = null;
            updateComputerList();
        }
        // ###END###{MeshServerConnect}

        // ###BEGIN###{ComputerSelectorScanner}
        // ###BEGIN###{Mode-NodeWebkit}

        //
        // Network scan
        //

        var globalAmtScanner = CreateAmtScanner(amtScanChangePresence);
        var globalAmtScannerResults = null;

        function showScanDialog() {
            if (xxdialogMode) return;
            var x = "Immettere un intervallo di indirizzi IP per la ricerca di dispositivi Intel AMT." + '<br /><br />';
            x += '<div style=height:20px><div style=float:right;width:260px;overflow:hidden><input id=idx_iprange style=width:204px placeholder="192.168.0.0/16" onkeyup=showScanDialogUpdate()></input><input id=idx_iprangebutton type=button value=Scan onclick=amtScanStartScan()></input></b></div><div>' + "Intervallo IP" + '</div></div>';
            x += '<br /><div id=idx_results style="width:100%;height:200px;background-color:white;border:1px gray solid;overflow-y:scroll"></div>';
            setDialogMode(11, "Scansione per dispositivi Intel&reg; AMT", 3, showScanDialogOk, x);
            QH('idx_results', '<div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Valori di intervallo IP di esempio" + '<br />192.168.0.100<br />192.168.0.0/16<br />192.168.0.1-192.168.0.100</div>');
            try { Q('idx_iprange').value = localStorage.getItem('scanrange'); } catch (ex) { }
            showScanDialogUpdate();
        }

        function showScanDialogUpdate() {
            QS('idx_iprange')['background-color'] = ((Q('idx_iprange').value.length > 0) ? 'white' : 'LightYellow');
            QE('idx_iprangebutton', Q('idx_iprange').value.length > 0);
            amtScanCheckbox();
        }

        // Populate the Intel AMT scan dialog box with the result of the RMCP scan
        function amtScanResult(scanner, result) {
            if ((xxdialogMode == undefined) || (!Q('idx_iprange'))) return;
            if (result == null) {
                // If no results where found, display a nice message
                QH('idx_results', '<div style=width:100%;text-align:center;margin-top:12px>Scan returned no results.</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.0.0/16<br />192.167.0.1-192.168.0.100</div>');
            } else {
                // Add the new result to the scan results dialog box
                var x = '', str = '<b>' + result.rinfo.address + '</b> - v' + result.ver;
                if (globalAmtScannerResults == null) { globalAmtScannerResults = {}; QH('idx_results', ''); }
                globalAmtScannerResults[result.rinfo.address] = result;
                if (result.state == 2) { if (result.tls == 1) { str += ' with TLS.'; } else { str += ' without TLS.'; } } else { str += ' not activated.'; }
                x += '<div style=margin-bottom:2px>';
                x += '<div class=j1 style=height:24px;float:left;background-color:white></div>';
                x += '<div class=g1 style=height:24px;float:left></div><div class=g2 style=height:24px;float:right></div><div style=height:24px;width:100%;background-color:#c9c9c9><div><div style=display:inline-block;margin-right:5px><input class=DevScanCheckbox tag="' + result.rinfo.address + '" type=checkbox onclick=amtScanCheckbox() /></div><div style=display:inline-block;margin-left:5px>' + str + '</div></div></div></div>';
                QA('idx_results', x);
            }
        }

        function amtScanStartScan() {
            var ip_range = Q('idx_iprange').value;
            try { localStorage.setItem('scanrange', ip_range); } catch (ex) { }
            globalAmtScannerResults = null;
            if (globalAmtScanner.performRangeScan('1', ip_range, amtScanResult) == false) {
                // The scan could not occur because of an error. Likely the user range was invalid.
                x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Impossibile scansionare questo intervallo di indirizzi." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Valori di intervallo IP di esempio" + '<br />192.168.0.100<br />192.168.0.0/16<br />192.167.0.1-192.168.0.100</div>';
            } else {
                // Show scanning...
                QH('idx_results', '<div style=width:100%;text-align:center;margin-top:12px>' + "Scansione ..." + '</div>');
            }
        }

        // Called when a scanned computer is checked or unchecked.
        function amtScanCheckbox() {
            var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
            for (var i in elements) { if (elements[i].checked) checkcount++; }
            QE('idx_dlgOkButton', checkcount > 0);
        }

        // Called when the OK button is pressed on the scan dialog
        function showScanDialogOk() {
            var elements = document.getElementsByClassName('DevScanCheckbox');
            for (var i in elements) {
                if (elements[i].checked) {
                    var ipaddr = elements[i].getAttribute('tag');
                    var result = globalAmtScannerResults[ipaddr];
                    computerlist.push({ 'h': Math.random(), 'name': ipaddr, 'host': ipaddr, 'tags': '', 'user': 'admin', 'pass': '', 'tls': result.tls, 'ver': result.ver });
                }
                saveComputers();
                updateComputerList();
            }
        }

        // Called by the scanner to change Intel AMT presense state
        function amtScanChangePresence(h, presence) {
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) return;
            // ###END###{MeshServerConnect}
            var element = Q('SS-' + h);
            if (element) { element.style['background-color'] = presence ? 'green' : 'red'; }

            // ###BEGIN###{Look-Commander}
            if (presence) { Q('SI-' + h).classList.remove('gray'); } else { Q('SI-' + h).classList.add('gray'); }
            // ###END###{Look-Commander}

            // If the computer that was updated is the current computer, update the details.
            if (currentcomputer && (currentcomputer.h == h)) { updateComputerDetails(); }
        }

        // Called when used clicks the "Scan for presense" menu option
        function NW_AmtScanMenu() {
            try { localStorage.setItem('scanForComputers', NW_AmtScanMenuItem.checked); } catch (ex) { }
            if (NW_AmtScanMenuItem.checked == true) { globalAmtScanner.start(); } else { globalAmtScanner.stop(); }
            updateComputerList();
        }

        // ###END###{Mode-NodeWebkit}
        // ###END###{ComputerSelectorScanner}

// ###END###{ComputerSelector}

// ###BEGIN###{ContextMenus}
        function handleContextMenu(e) {
            hideContextMenu();
            if (xxdialogMode) return;
            // ###BEGIN###{ComputerSelector}
            toolmenuclick(-1);
            // ###END###{ComputerSelector}
            var cm = document.elementFromPoint(e.pageX, e.pageY);
            while (cm && cm != null && cm.getAttribute('cm') == null) { cm = cm.parentElement; }
            if (cm && cm != null && cm.getAttribute('cm') != null) {
                var x = '', menus = cm.getAttribute('cm').split('|');
                if (cm.getAttribute('class') == 'computeritem') cm.click();
                for (var i in menus) {
                    if (menus[i] == '-') {
                        x += '<hr style="border:1px solid lightgray" />';
                    } else {
                        var menus2 = menus[i].split('#');
                        x += '<div class=cmtext onclick=\"hideContextMenu();' + menus2[1] + '\"><b>' + menus2[0] + '</b></div>';
                    }
                }
                QS('contextMenu').top = e.pageY + 'px';
                QS('contextMenu').left = e.pageX + 'px';
                QH('contextMenu', x);
                QV('contextMenu', true);
                haltEvent(e);
                return false;
            }
        }

        function hideContextMenu() { QV('contextMenu', false); }
// ###END###{ContextMenus}

        //
        // BOTTOM INFORMATION STRING
        //

// ###BEGIN###{VersionWarning}
        // Returns true if Intel AMT needs to be updated
        function checkAmtVersion(version) {
            var vSplit = version.split('.');
            var v1 = parseInt(vSplit[0]);
            var v2 = parseInt(vSplit[1]);
            var v3 = parseInt(vSplit[2]);
            var vx = ((v2 * 1000) + v3);
            var ok = 0;

            if ((v1 <= 5) || (v1 >= 12)) { ok = 1; } // Intel AMT less then v5 and v12 and beyond, all ok.
            else if ((v1 == 6) && (vx >= 2061)) { ok = 1; } // 1st Gen Core
            else if ((v1 == 7) && (vx >= 1091)) { ok = 1; } // 2st Gen Core
            else if ((v1 == 8) && (vx >= 1071)) { ok = 1; } // 3st Gen Core
            else if ((v1 == 9)) { if ((v2 < 5) && (vx >= 1041)) { ok = 1; } else if (vx >= 5061) { ok = 1; } } // 4st Gen Core
            else if ((v1 == 10) && (vx >= 55)) { ok = 1; } // 5st Gen Core
            else if (v1 == 11) {
                if ((v2 < 5) && (vx >= 25)) { ok = 1; } // 6st Gen Core
                else if (vx >= 6027) { ok = 1; } // 7st Gen Core
            }
            return (ok == 0);
        }
// ###END###{VersionWarning}

        function processSystemVersion(stack, name, responses, status) {
            if (status == 200 || status == 400) {
                var v;
                if (status == 200) {
                    //amtlogicalelements = responses;
                    amtlogicalelements = [];
                    if (responses != null) {
                        if (responses['CIM_SoftwareIdentity'] != null && responses['CIM_SoftwareIdentity'].responses != null) {
                            amtlogicalelements = responses['CIM_SoftwareIdentity'].responses;
                            if (responses['AMT_SetupAndConfigurationService'] != null && responses['AMT_SetupAndConfigurationService'].response != null) {
                                amtlogicalelements.push(responses['AMT_SetupAndConfigurationService'].response);
                            }
                        }
                    }
                    if (amtlogicalelements.length == 0) { console.error('ERROR: Could not get Intel AMT version.'); disconnect(); return; } // Could not get Intel AMT version, disconnect();
                    v = getInstance(amtlogicalelements, 'AMT')['VersionString'];
                } else {
                    v = stack.wsman.comm.amtVersion;
                    if (!v) { errcheck(400, stack); return; }
                }
                amtversion = parseInt(v.split('.')[0]);
                amtversionmin = parseInt(v.split('.')[1]);

                // If this is Intel AMT 16 or higher, boost the stack speed by allowing HTTP pipelining.
                //if (amtversion > 15) {
                    //stack.MaxActiveEnumsCount = 2;
                    //stack.wsman.comm.MaxActiveAjaxCount = 2;
                //}

                // ###BEGIN###{Mode-NodeWebkit}
                // Perform Intel ME authentication if available.
                if ((amtversion >= 15) && (wsstack.comm.xtlsCertificate != null)) {
                    stack.amtauthnonce = require('crypto').randomBytes(20).toString('base64');
                    stack.AMT_GeneralSettings_AMTAuthenticate(stack.amtauthnonce, function (stack, name, response, status) {
                        //console.log('AMTAuthenticate', status, response);
                        //status = 200;
                        //response = JSON.parse('{"Header":{"To":"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous","RelatesTo":"15","Action":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings/AMTAuthenticateResponse","MessageID":"uuid:00000000-8086-8086-8086-00000000008E","ResourceURI":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings","Method":"AMTAuthenticate"},"Body":{"Nonce":"s5PzXOyJqlPwnE/FJ1Imk2tLc2s=","UUID":"465A544C39335830B0304A51465A544C","FQDN":"","FWVersion":"15.0.10.7000","AMTSVN":1,"Signature":"cT4DpT2VpDi0jq+3tIswntXIIitCQV6QxMbXMZryob7RYRyazW9YFKrX5nfu0tPpTqLEP9P+C8pVT4ZngU1TIrn2ptVw/xCKmOn56Y62U0Gv+fQSG1+AJFRej+W7Clv4","LengthOfCertificates":[602,638,631,708],"Certificates":"MIICVjCCAd2gAwIBAgIQSsxzEcw7W5elVuRWfkbN1zAKBggqhkjOPQQDAzAeMRwwGgYDVQQDDBNDU01FIFRHTCBBTVQgIDAxU0RFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowFTETMBEGA1UEAwwKQU1UIFdTLU1BTjB2MBAGByqGSM49AgEGBSuBBAAiA2IABOiUImnj9foD828QWknCF47SuIhwKn+AzhcgPz7IaUb/Z9KTPn57VfxahHBObijKRodtcxao0Jip/0sM3wbXkHvF03BLdxP6/ab5uMYLH+ZDjdlwC69qkjQtXciIzml8u6OB6DCB5TAfBgNVHSMEGDAWgBS4jxQZFu/qvArLmfxFoa+HO3ZPhjAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEB/wQEAwIGgDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDZwAwZAIwMlkcpHt5ydDt2hmnF+pJxLzH6oF3K2XPviuudyQ8DtHfuziWXgI7t2KS/Y5tOFEAAjBxLW0MkEcpDlsKNS0ASNxOhi6neEEQaxT93EJh3J/Z0SU8qYdE2/qtfe087XhCvlowggJ6MIICAaADAgECAgUBBBwAIDAKBggqhkjOPQQDAzAjMSEwHwYDVQQDDBhDU01FIFRHTCBTVk4wMSBLZXJuZWwgREUwHhcNMjAwNzIzMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjAeMRwwGgYDVQQDDBNDU01FIFRHTCBBTVQgIDAxU0RFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAES/XBgK8rDlDycUzCocI1TrrrcQzD2Okq2BJhfqSg6MKxRMyei903Ewl94yl+tFsWoLuPiZDVE/bfxJghTynuGxk38YI8Qn8L3mPL+ahh3tSxWxC3kdszrU9dgObLF+2Io4IBCDCCAQQwHwYDVR0jBBgwFoAUzxraD/dMy5Zf2FiUKGctnPWwk30wHQYDVR0OBBYEFLiPFBkW7+q8CsuZ/EWhr4c7dk+GMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMIGgBgNVHR8EgZgwgZUwgZKgSqBIhkZodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jcmxzL09uRGllX0NBX0NTTUVfSW5kaXJlY3QuY3JsokSkQjBAMSYwJAYDVQQLDB1PbkRpZSBDQSBDU01FIEludGVybWVkaWF0ZSBDQTEWMBQGA1UEAwwNd3d3LmludGVsLmNvbTAKBggqhkjOPQQDAwNnADBkAjBiU4sHamrnSkvkwpTbVJah30CSGycVSwlUCUnXxFBFcCmXQeuXdElJiXhZyO5CQf8CMBxnQghoKlmUCKhzEYHjDMdXAKJcIapz6ksRDuYycxOlEpyBjei5tU5Nq16qDdt0njCCAnMwggH5oAMCAQICAQEwCgYIKoZIzj0EAwMwGjEYMBYGA1UEAwwPQ1NNRSBUR0wgUk9NIERFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowIzEhMB8GA1UEAwwYQ1NNRSBUR0wgU1ZOMDEgS2VybmVsIERFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEtfPOoxER7WKkOQQFPnDBikHOrIkNZA1si7sFV1Y1tSBF4HCCl0BfXo5GqsOxzwJ2JcJLiP16ZP3rMcOOpufVLwPwN/0jmP1/KDeANgmwGLLvjAuHfx/KRU3MqkDdSLbfo4IBCDCCAQQwHwYDVR0jBBgwFoAUsd+j/J4YMaOrY0I0x9dKYND8mMQwHQYDVR0OBBYEFM8a2g/3TMuWX9hYlChnLZz1sJN9MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKsMIGgBgNVHR8EgZgwgZUwgZKgSqBIhkZodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jcmxzL09uRGllX0NBX0NTTUVfSW5kaXJlY3QuY3JsokSkQjBAMSYwJAYDVQQLDB1PbkRpZSBDQSBDU01FIEludGVybWVkaWF0ZSBDQTEWMBQGA1UEAwwNd3d3LmludGVsLmNvbTAKBggqhkjOPQQDAwNoADBlAjB0WjT9RuE7v+dm2EM2uf7uZ3Pv3KAKZzBkpvokIbuO1qE3FS36mf3kKfl58hMhfosCMQD4NyxKd28cm9ZfW7eOEetEwXXDgCtq+rfzCXbJWDQvkYpnS4LPxIXxEsiN6/scTH0wggLAMIICRqADAgECAhBAAAAAAAAAAAAAAAAAAAAAMAoGCCqGSM49BAMDMEgxLjAsBgNVBAsMJU9uIERpZSBDU01FIERfVEdMIERFQlVHMDAwIElzc3VpbmcgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wHhcNMTkwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjAaMRgwFgYDVQQDDA9DU01FIFRHTCBST00gREUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ4g65/2ziA9osYJXOdQ81/PobyJmcTqSU8CMcVk3OyWhGjaczREvl+DvZpd5+2CYAxSr3ItlK5Jn3z1xG4mwHRzH0FFdu7Ooxf7kSH5dXnSO7hv6q/y97+KTy6odfzRuqjggEhMIIBHTAfBgNVHSMEGDAWgBQ7McrVw0uS10jI/ZKqda6dMkoGQjAdBgNVHQ4EFgQUsd+j/J4YMaOrY0I0x9dKYND8mMQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAa4wYgYIKwYBBQUHAQEEVjBUMFIGCCsGAQUFBzAChkZodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jZXJ0cy9UR0xfREVCVUcwMDBfT25EaWVfQ0EuY2VyMFYGA1UdHwRPME0wS6BJoEeGRWh0dHBzOi8vdHNERS5pbnRlbC5jb20vY29udGVudC9PbkRpZUNBL2NybHMvVEdMX0RFQlVHMDAwX09uRGllX0NBLmNybDAKBggqhkjOPQQDAwNoADBlAjAjX8BHXjQGsr1uqkCDdqRRzT2yQNLU4i85H+mJboRaAB2h09mISKagGU0m3DXywmICMQDmTjjpPjCJye9m2u/csfkUAn7rP1FLmdJHtT9qN968CACWQQ356e8s3XgNpNtexJU=","ReturnValue":0,"ReturnValueStr":"SUCCESS"}}'); // Sample Response 1
                        //response = JSON.parse('{"Header":{"To":"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous","RelatesTo":"15","Action":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings/AMTAuthenticateResponse","MessageID":"uuid:00000000-8086-8086-8086-0000000000F8","ResourceURI":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings","Method":"AMTAuthenticate"},"Body":{"Nonce":"NlfyHfo322EtefP1q5s92K+szBw=","UUID":"465A544C39335830B0304A51465A544C","FQDN":"","FWVersion":"15.0.10.7000","AMTSVN":1,"Signature":"9jBx0HfvNECPrMrg16px2RGDu/qdgrUyguOamlJ5hpiYgt9ZPrMz6/WgYY5nbnT6zBxSTUP+AqEzcmA6oWunYHZQJprY9iDdew4PPIHWqGZGgqh/10m3aYHwy+TKk/Ab","LengthOfCertificates":[603,638,631,708],"Certificates":"MIICVzCCAd2gAwIBAgIQSsxzEcw7W5elVuRWfkbN1zAKBggqhkjOPQQDAzAeMRwwGgYDVQQDDBNDU01FIFRHTCBBTVQgIDAxU0RFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowFTETMBEGA1UEAwwKQU1UIFdTLU1BTjB2MBAGByqGSM49AgEGBSuBBAAiA2IABOiUImnj9foD828QWknCF47SuIhwKn+AzhcgPz7IaUb/Z9KTPn57VfxahHBObijKRodtcxao0Jip/0sM3wbXkHvF03BLdxP6/ab5uMYLH+ZDjdlwC69qkjQtXciIzml8u6OB6DCB5TAfBgNVHSMEGDAWgBS4jxQZFu/qvArLmfxFoa+HO3ZPhjAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEB/wQEAwIGgDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDaAAwZQIwYCfw7GuUi9XxfBfhO/LYUbSb3pd65tkpRSLjIhsj9uMG9DFbMVUy9aicvZt7NYwXAjEAtAdHvcmoI/fZfw2Mo7TooojLe+xfHzZ5NyZyVlPaVyya25K/3kE05gvQO1jvk/ZcMIICejCCAgGgAwIBAgIFAQQcACAwCgYIKoZIzj0EAwMwIzEhMB8GA1UEAwwYQ1NNRSBUR0wgU1ZOMDEgS2VybmVsIERFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQ1NNRSBUR0wgQU1UICAwMVNERTB2MBAGByqGSM49AgEGBSuBBAAiA2IABEv1wYCvKw5Q8nFMwqHCNU6663EMw9jpKtgSYX6koOjCsUTMnovdNxMJfeMpfrRbFqC7j4mQ1RP238SYIU8p7hsZN/GCPEJ/C95jy/moYd7UsVsQt5HbM61PXYDmyxftiKOCAQgwggEEMB8GA1UdIwQYMBaAFM8a2g/3TMuWX9hYlChnLZz1sJN9MB0GA1UdDgQWBBS4jxQZFu/qvArLmfxFoa+HO3ZPhjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDZwAwZAIwYlOLB2pq50pL5MKU21SWod9AkhsnFUsJVAlJ18RQRXApl0Hrl3RJSYl4WcjuQkH/AjAcZ0IIaCpZlAiocxGB4wzHVwCiXCGqc+pLEQ7mMnMTpRKcgY3oubVOTateqg3bdJ4wggJzMIIB+aADAgECAgEBMAoGCCqGSM49BAMDMBoxGDAWBgNVBAMMD0NTTUUgVEdMIFJPTSBERTAeFw0yMDA3MjMwMDAwMDBaFw00OTEyMzEyMzU5NTlaMCMxITAfBgNVBAMMGENTTUUgVEdMIFNWTjAxIEtlcm5lbCBERTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLXzzqMREe1ipDkEBT5wwYpBzqyJDWQNbIu7BVdWNbUgReBwgpdAX16ORqrDsc8CdiXCS4j9emT96zHDjqbn1S8D8Df9I5j9fyg3gDYJsBiy74wLh38fykVNzKpA3Ui236OCAQgwggEEMB8GA1UdIwQYMBaAFLHfo/yeGDGjq2NCNMfXSmDQ/JjEMB0GA1UdDgQWBBTPGtoP90zLll/YWJQoZy2c9bCTfTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICrDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDaAAwZQIwdFo0/UbhO7/nZthDNrn+7mdz79ygCmcwZKb6JCG7jtahNxUt+pn95Cn5efITIX6LAjEA+DcsSndvHJvWX1u3jhHrRMF1w4Aravq38wl2yVg0L5GKZ0uCz8SF8RLIjev7HEx9MIICwDCCAkagAwIBAgIQQAAAAAAAAAAAAAAAAAAAADAKBggqhkjOPQQDAzBIMS4wLAYDVQQLDCVPbiBEaWUgQ1NNRSBEX1RHTCBERUJVRzAwMCBJc3N1aW5nIENBMRYwFAYDVQQDDA13d3cuaW50ZWwuY29tMB4XDTE5MDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowGjEYMBYGA1UEAwwPQ1NNRSBUR0wgUk9NIERFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEOIOuf9s4gPaLGCVznUPNfz6G8iZnE6klPAjHFZNzsloRo2nM0RL5fg72aXeftgmAMUq9yLZSuSZ989cRuJsB0cx9BRXbuzqMX+5Eh+XV50ju4b+qv8ve/ik8uqHX80bqo4IBITCCAR0wHwYDVR0jBBgwFoAUOzHK1cNLktdIyP2SqnWunTJKBkIwHQYDVR0OBBYEFLHfo/yeGDGjq2NCNMfXSmDQ/JjEMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGuMGIGCCsGAQUFBwEBBFYwVDBSBggrBgEFBQcwAoZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY2VydHMvVEdMX0RFQlVHMDAwX09uRGllX0NBLmNlcjBWBgNVHR8ETzBNMEugSaBHhkVodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jcmxzL1RHTF9ERUJVRzAwMF9PbkRpZV9DQS5jcmwwCgYIKoZIzj0EAwMDaAAwZQIwI1/AR140BrK9bqpAg3akUc09skDS1OIvOR/piW6EWgAdodPZiEimoBlNJtw18sJiAjEA5k446T4wicnvZtrv3LH5FAJ+6z9RS5nSR7U/ajfevAgAlkEN+envLN14DaTbXsSV","ReturnValue":0,"ReturnValueStr":"SUCCESS"}}'); // Sample Response 2

                        if (status == 200) {
                            stack.amtauth = response.Body;
                            stack.amtauth.CertificatesDer = [];
                            var certs = [], urlList = [], certsbin = atob(stack.amtauth.Certificates), cptr = 0;
                            for (var i = 0; i < stack.amtauth.LengthOfCertificates.length; i++) {
                                var bin = certsbin.substring(cptr, cptr + stack.amtauth.LengthOfCertificates[i]);
                                stack.amtauth.CertificatesDer.push(bin);
                                var cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(bin)); // Node-forge does not support ECC, but we are using a modified Node-forge that can still parse the cert.
                                cert.xCrlUrls = getExtensionUrls(cert, 'cRLDistributionPoints');
                                cert.xParentUrls = getExtensionUrls(cert, { id: '1.3.6.1.5.5.7.1.1' });
                                cert.xFingerprint = forge.md.sha256.create().update(bin).digest().toHex().toUpperCase();
                                cptr += stack.amtauth.LengthOfCertificates[i];
                                certs.push(cert);
                                if ((cert.xCrlUrls.length > 0) && (urlList.indexOf(cert.xCrlUrls[0]) == -1)) { urlList.push(cert.xCrlUrls[0]); }
                            }

                            // If the top certificate has a parent URL, add it to the list of URL's to fetch.
                            if ((certs.length > 0) && (certs[certs.length - 1].xParentUrls.length > 0) && (urlList.indexOf(certs[certs.length - 1].xParentUrls[0]) == -1)) {
                                urlList.push(certs[certs.length - 1].xParentUrls[0]);
                            }

                            stack.amtauth.Certificates = certs;
                            stack.amtauth.ClientNonce = stack.amtauthnonce;
                            delete stack.amtauth.LengthOfCertificates;
                            stack.amtauth.uuidStr = guidToStr(stack.amtauth.UUID).toLowerCase();

                            var trustedCsmeRoots = [
                                '3BA13766B1889DCB1E2D55BACCC9EC087452F78783E2EBAFD918FF4ED6ACC840', // www.intel.com / OnDie CA DEBUG Root Cert Signing CA
                                'C001DF02B31A60A2B37130365956400A2AFCFD147E8552FD7EA3F17F2AB0D457', // www.intel.com / ODCA CA2 CSME Intermediate CA
                                '5E3EEE5748AC13E0B3D1227FCDC4751AA1402DDE8031D21F63CB4ECF43F02440'  // www.intel.com / OnDie CA CSME Intermediate CA
                            ];

                            // Load the entire certificate chain and CRL's
                            var urlLoad = function (url, data) {
                                if (data == null) return;
                                for (var j in certs) {
                                    if ((certs[j].xCrlUrls.length > 0) && (certs[j].xCrlUrls[0] == url)) { certs[j].xCrl = data; }
                                    if ((j == (certs.length - 1)) && (certs[j].xParentUrls.length > 0) && (certs[j].xParentUrls[0] == url)) {
                                        var xcert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(data)); // Node-forge does not support ECC, but we are using a modified Node-forge that can still parse the cert.
                                        xcert.xCrlUrls = getExtensionUrls(xcert, 'cRLDistributionPoints');
                                        xcert.xParentUrls = getExtensionUrls(xcert, { id: '1.3.6.1.5.5.7.1.1' });
                                        xcert.xFingerprint = forge.md.sha256.create().update(data).digest().toHex().toUpperCase();
                                        if (trustedCsmeRoots.indexOf(xcert.xFingerprint) >= 0) { xcert.xTrusted = true; }
                                        certs.push(xcert);
                                        stack.amtauth.CertificatesDer.push(data);
                                        if ((xcert.xCrlUrls.length > 0) && (urlList.indexOf(xcert.xCrlUrls[0]) == -1)) { getCertUrl(xcert.xCrlUrls[0], urlLoad); }
                                        if ((xcert.xParentUrls.length > 0) && (urlList.indexOf(xcert.xParentUrls[0]) == -1)) { urlList.push(xcert.xParentUrls[0]); getCertUrl(xcert.xParentUrls[0], urlLoad); }
                                        return;
                                    }
                                }
                            }
                            for (var i in urlList) { getCertUrl(urlList[i], urlLoad); }
                        } else {
                            console.log('AMTAuthenticate', status, response);
                        }
                        delete stack.amtauthnonce;
                    });
                }
                // ###END###{Mode-NodeWebkit}

                // ###BEGIN###{ComputerSelector}
                if (stack.wsman.comm.digestRealm && (currentcomputer['digestrealm'] != stack.wsman.comm.digestRealm)) {
                    currentcomputer['digestrealm'] = stack.wsman.comm.digestRealm;
                    // ###BEGIN###{ComputerSelector-Local}
                    saveComputers();
                    // ###END###{ComputerSelector-Local}
                    updateComputerDetails();
                }
                // ###END###{ComputerSelector}

                // ###BEGIN###{VersionWarning}
                QV('id_versionWarning', checkAmtVersion(v));
                // ###END###{VersionWarning}
                // ###BEGIN###{!Mode-Firmware}
                //if (amtversion > 10) { wsstack.comm.MaxActiveAjaxCount = 4; amtstack.MaxActiveEnumsCount = 1; console.log('HTTP Pipelining activated'); } // With Intel AMT 11 and higher, use HTTP pipelining.
                // ###END###{!Mode-Firmware}

                PullSystemStatus();
                updateSystemStatus();

                // Perform loads more WSMAN only if needed
                if ((urlvars['kvmonly'] != 1) && (fullscreenonly == false)) {
                    PullUserInfo();

                    // ###BEGIN###{Alarms}
                    if (amtversion >= 8) PullAlarms();
                    // ###END###{Alarms}
                }

                // ###BEGIN###{Mode-NodeWebkit}
                if (wsstack.comm.getPeerCertificate() != null) {
                    QV('tlsNotification1', wsstack.comm.xtlsCheck == 1);
                    QV('tlsNotification2', wsstack.comm.xtlsCheck == 2);
                    QV('tlsNotification3', wsstack.comm.xtlsCheck == 3);
                }
                if (currentcomputer['tlscerthash2']) delete currentcomputer['tlscerthash2'];
                if (currentcomputer['tlscert2']) delete currentcomputer['tlscert2'];
                // ###END###{Mode-NodeWebkit}

                // Connection callback
                if (connectFunc) { connectFunc(connectFuncTag); connectFunc = null; connectFuncTag = null; }

                // ###BEGIN###{Desktop}
                if (urlvars['kvm'] == 1) { go(14); connectDesktop(); }
                if ((urlvars['kvmfull'] == 1) || (urlvars['kvmonly'] == 1)) { go(14); connectDesktop(); }
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (urlvars['sol'] == 1) { go(13); connectTerminal(); }
                // ###END###{Terminal}

                // ###BEGIN###{Scripting}
                // ###BEGIN###{Mode-NodeWebkit}
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                if (urlvars['host'] && urlvars['script']) {
                    try {
                        var data = require('fs').readFileSync(urlvars['script'], 'utf8');
                        if (data) { script_onScriptRead( { target: { result: data }} ); }
                    } catch (e) { messagebox("Esegui script", "File di script non valido.") }
                }
                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###END###{Mode-NodeWebkit}
                // ###END###{Scripting}
            } else {
                errcheck(status, stack);
            }
        }

        // Control the state of all refresh buttons
        var refreshButtonsState = true;
        function refreshButtons(x) {
            if (refreshButtonsState == x) return;
            refreshButtonsState = x;
            var i = 0, e = document.getElementsByTagName('input');
            for (; i < e.length; i++) { if (e[i].name == 'refreshbtn') { e[i].disabled = !x; } }
        }

        // Store certificate pinning
        // ###BEGIN###{Mode-NodeWebkit}
        function storeCertPinning(host, hash) {
            var pins = {};
            try { pins = JSON.parse(localStorage.getItem('amtcertpins')); } catch (e) { }
            if ((pins == null) || (typeof pins != 'object')) { pins = {}; }
            if (hash) { pins[host] = hash; } else { delete pins[host]; }
            try { localStorage.setItem('amtcertpins', JSON.stringify(pins)); } catch (ex) { }
        }

        function getCertPinnings() { try { var x = JSON.parse(localStorage.getItem('amtcertpins')); if ((x == null) || (typeof x != 'object')) return {}; return x; } catch (e) { return {} } }
        function getCertPinning(host) { return getCertPinnings()[host]; }

        // ###END###{Mode-NodeWebkit}

        // Display TLS certificate
        // ###BEGIN###{Mode-NodeWebkit}
        var showTlsCertTempCert;
        function showTlsCert(buttons, msg, cert, tag, func) {
            if (xxdialogMode) return;
            var c = showTlsCertTempCert = cert?cert:wsstack.comm.getPeerCertificate(), x = '<br>';
            if (msg) x = '<div>' + msg + '</div><br />';
            // ###BEGIN###{FileSaver}
            x += addHtmlValue("Certificato", c.raw.length + " byte," + '<a style=cursor:pointer;color:blue onclick=downloadTlsCert()>' + "Scarica" + '</a>');
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            x += addHtmlValue("Certificato", c.raw.length + " byte");
            // ###END###{!FileSaver}

            // Display certificate key usages
            var y = [];
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.2') >= 0) { y.push(NoBreak("Client TLS")); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.3') >= 0) { y.push(NoBreak("Firma del codice")); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.4') >= 0) { y.push("E-mail"); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.1') >= 0) { y.push(NoBreak("Server TLS")); }
            if (c.ext_key_usage.indexOf('2.16.840.1.113741.1.2.1') >= 0) { y.push(NoBreak("Console Intel&reg; AMT")); }
            if (c.ext_key_usage.indexOf('2.16.840.1.113741.1.2.2') >= 0) { y.push(NoBreak("Agente Intel&reg; AMT")); }
            if (c.ext_key_usage.indexOf('2.16.840.1.113741.1.2.3') >= 0) { y.push(NoBreak("Attivazione Intel&reg; AMT")); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.8') >= 0) { y.push(NoBreak("Timestamp")); }
            if (y.length > 0) { x += addHtmlValueNoTitle("Utilizzo del certificato", y.join(', ') + '.') + '<br clear=all />'; }

            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Oggetto del certificato" + '</i></div><br>';
            for (var i in c.subject) { if (c.subject[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(MakeToArray(c.subject[i]).join(', '))); } }
            x += addHtmlValueNoTitle("impronta digitale", c.fingerprint.substring(0,29) + '<br />' + c.fingerprint.substring(30));
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificato dell'Emittente" + '</i></div><br>';
            for (var i in c.issuer) { if (c.issuer[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(MakeToArray(c.issuer[i]).join(', '))); } }
            if (func == null) { func = showTlsCertDefault; }
            setDialogMode(11, "Certificato TLS -" + EscapeHtml(c.subject['CN']), buttons, func, x, { c: c, m: tag });
        }

        function showTlsCertDefault(b, args) {
            var cert = args.c, mode = args.m;
            if (b == 0) { disconnect(); }
            if (b == 1) {
                currentcomputer['tlscerthash'] = cert.fingerprint.split(':').join('').toLowerCase();
                currentcomputer['tlscert'] = cert.raw.toString('hex');
                currentcomputer['tlscerthash2'] = cert.fingerprint.split(':').join('').toLowerCase();
                currentcomputer['tlscert2'] = cert.raw.toString('hex');
                storeCertPinning(currentcomputer.host, cert.fingerprint.split(':').join('').toLowerCase());
                // ###BEGIN###{ComputerSelector-Local}
                saveComputers();
                // ###END###{ComputerSelector-Local}
                updateComputerDetails();
                if (mode == 1) {
                    // Reconnect immidiatly
                    computerConnect(undefined, currentcomputer['h'], 0, true);
                }
            }
        }

        function downloadTlsCert() {
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', showTlsCertTempCert.subject['CN'] + '.cer');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, showTlsCertTempCert.raw, 'binary', function () { }); }, false);
            chooser.click();
        }

        function switchToTls() {
            if (xxTlsCurrentCert == null) {
                setDialogMode(11, "Passa a TLS", 3, switchToTls1, "La connessione al momento non è protetta. Fare clic su OK per configurare Intel AMT con TLS e passare a una connessione protetta.");
            } else {
                setDialogMode(11, "Passa a TLS", 3, switchToTls1, "La connessione al momento non è protetta e Intel AMT è già configurata con TLS. Fare clic su OK per passare a una connessione sicura.");
            }
        }

        function switchToTls1() {
            // Check if Intel AMT is already setup with TLS.
            if (xxTlsCurrentCert == null) {
                // TLS is not setup, start by asking Intel AMT to generate a key pair
                messagebox("Configurazione TLS", "Generazione della chiave del certificato ...");
                amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, switchToTls2);
            } else {
                // Setup the certificate pinning and reconnect
                var cert = null;
                try { cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(xxCertificates[xxTlsCurrentCert].X509Certificate)); } catch (ex) { messagebox("Certificato TLS", "Impossibile leggere il certificato TLS: " + ex); return; }
                currentcomputer['tlscert'] = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex();
                currentcomputer['tlscerthash'] = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex();
                currentcomputer['tls'] = 1;
                updateComputerDetails();
                saveComputers();

                // Disconnect and reconnect immidiatly
                disconnect();
                computerConnect(undefined, currentcomputer['h'], 0, true);
            }
        }

        function switchToTls2(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi. Stato: " + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi," + response.Body['ReturnValueStr']); return; }

            // Get the new key pair
            messagebox("Configurazione TLS", "Recupero chiave certificato ...");
            amtstack.Enum('AMT_PublicPrivateKeyPair', switchToTls3, response.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']);
        }

        function switchToTls3(stack, serviceName, response, status, tag) {
            if (status != 200) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi. Stato: " + status); return; }
            var DERKey = null;
            for (var i in response) { if (response[i]['InstanceID'] == tag) DERKey = response[i]['DERKey']; }

            // Sign the key pair using the CA certifiate
            messagebox("Configurazione TLS", "Creazione del certificato TLS ...");

            var name = ''
            try { name = amtsysstate['AMT_GeneralSettings'].response['HostName']; } catch (ex) { }
            if ((name == null) || (name == '')) { name = currentcomputer['name']; }
            if ((name == null) || (name == '')) { name = currentcomputer['host']; }
            var cert = amtcert_signWithCaKey(DERKey, null, { 'CN': name, 'O': "Nessuna", 'ST': "Nessuna", 'C': "Nessuna" }, { 'CN': "Certificato radice non attendibile" }, { name: 'extKeyUsage', serverAuth: true });
            if (cert == null) { messagebox("Rilascio certificato", "Impossibile firmare il certificato."); return; }

            // Save cert and cert hash in computer list
            messagebox("Configurazione TLS", "Caricamento certificato TLS ...");
            currentcomputer['tlscert'] = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex();
            currentcomputer['tlscerthash'] = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex();
            updateComputerDetails();
            saveComputers();

            // Place the resulting signed certificate back into AMT
            var pem = forge.pki.certificateToPem(cert).replace(/(\r\n|\n|\r)/gm, '');
            amtstack.AMT_PublicKeyManagementService_AddCertificate(pem.substring(27, pem.length - 25), switchToTls4);
        }

        function switchToTls4(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi. Stato: " + status); return; }

            messagebox("Configurazione TLS", "Impostazione del certificato TLS ...");
            var certInstanceId = response.Body['CreatedCertificate']['ReferenceParameters']['SelectorSet']['Selector']['Value'];

            // Set the TLS certificate
            setTlsSecurityPendingCalls = 3;
            if (xxTLSCredentialContext.length > 0) {
                // Modify the current context
                var newTLSCredentialContext = Clone(xxTLSCredentialContext[0]);
                newTLSCredentialContext['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'] = certInstanceId;
                amtstack.Put('AMT_TLSCredentialContext', newTLSCredentialContext, switchToTls5, 0, 1);
            } else {
                // Add a new security context
                amtstack.Create('AMT_TLSCredentialContext', {
                    'ElementInContext': '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + certInstanceId + '</w:Selector></w:SelectorSet></a:ReferenceParameters>',
                    'ElementProvidingContext': '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_TLSProtocolEndpointCollection') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="ElementName">TLSProtocolEndpointInstances Collection</w:Selector></w:SelectorSet></a:ReferenceParameters>'
                }, switchToTls5);
            }

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // Remote TLS settings
            var xxTlsSettings2 = Clone(xxTlsSettings);
            xxTlsSettings2[remoteNdx]['Enabled'] = true;
            xxTlsSettings2[remoteNdx]['MutualAuthentication'] = false;
            xxTlsSettings2[remoteNdx]['AcceptNonSecureConnections'] = true;
            delete xxTlsSettings2[remoteNdx]['TrustedCN'];

            // Local TLS settings
            xxTlsSettings2[localNdx]['Enabled'] = true;
            delete xxTlsSettings2[localNdx]['TrustedCN'];

            // Update TLS settings
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[0], switchToTls5, 0, 1, xxTlsSettings2[0]);
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[1], switchToTls5, 0, 1, xxTlsSettings2[1]);
        }

        function switchToTls5(stack, name, response, status) {
            if (stack) {
                if (status != 200) { messagebox('', "Impossibile impostare il certificato TLS, stato =" + status); return; }
                if (response.Body['ReturnValueStr'] && !methodcheck(response)) return;
            }

            // Check if all the calls are done & perform a commit
            if ((--setTlsSecurityPendingCalls) == 0) {
                messagebox("Configurazione TLS", "Esecuzione del commit ...");
                amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, switchToTls6);
            }
        }

        function switchToTls6(stack, name, response, status) {
            if (status != 200) { messagebox('', "Impossibile impostare la sicurezza TLS, status =" + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossibile impostare la sicurezza TLS, errore: " + response.Body['ReturnValueStr']); return; }

            // Switch current computer to TLS
            messagebox("Configurazione TLS", "Configurazione TLS completata.");
            currentcomputer['tls'] = 1;
            updateComputerDetails();
            saveComputers();

            setTimeout(function () {
                setDialogMode();

                // Disconnect and reconnect immidiatly
                disconnect();
                computerConnect(undefined, currentcomputer['h'], 0, true);
            }, 2000);
        }

        // ###END###{Mode-NodeWebkit}

        //
        // SYSTEM STATUS PANEL
        //

        // ###BEGIN###{PowerControl}
        function PullPowerState() {
            if (amtstack && amtstack.GetPendingActions() == 0 && amtsysstate && amtsysstate['CIM_ServiceAvailableToElement']) {
                amtstack.Enum('CIM_ServiceAvailableToElement', function (stack, name, responses, status) {
                    if (status != 200) return; // If the polling fails, just skip it.
                    amtsysstate['CIM_ServiceAvailableToElement'].responses = responses;
                    if ((amtversion > 9) && (amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0) && (amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] == 2)) {
                        // If Intel AMT 10+ and powered on, poll the OS power state.
                        amtstack.Get('IPS_PowerManagementService', function (stack, name, response, status) {
                            if (status == 200) { amtsysstate['IPS_PowerManagementService'].response = response.Body; updateSystemStatus(); }
                        });
                    } else {
                        updateSystemStatus();
                    }
                });

            }
        }
        // ###END###{PowerControl}

        function PullSystemStatus(x) {
            refreshButtons(false);
            amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(processSystemTime);
            // ###BEGIN###{Look-Intel-SBT}
            amtstack.BatchEnum('', ['*AMT_GeneralSettings'], processSystemStatus);
            // ###END###{Look-Intel-SBT}
            // ###BEGIN###{!Look-Intel-SBT}
            var query = ['CIM_ServiceAvailableToElement', '*AMT_GeneralSettings', 'AMT_EthernetPortSettings', '*AMT_RedirectionService', 'CIM_ElementSettingData', '*AMT_BootCapabilities'];
            if (amtversion > 5) query.push('IPS_IPv6PortSettings', '*CIM_KVMRedirectionSAP', '*IPS_OptInService','*IPS_KVMRedirectionSettingData');
            if (amtversion > 9) query.push('*IPS_ScreenConfigurationService', '*IPS_PowerManagementService');
            if (amtversion > 15) query.push('*CIM_BootService');
            // ###BEGIN###{NetAuth}
            if (amtversion > 2) query.push('*AMT_8021XProfile');
            // ###END###{NetAuth}
            amtstack.BatchEnum('', query, processSystemStatus, true);
            // ###END###{!Look-Intel-SBT}
            // ###BEGIN###{Wireless}
            if (x == 1) PullWireless();
            // ###END###{Wireless}
        }

        function processSystemTime(stack, name, responses, status) {
            if (errcheck(status, stack)) return;
            if (status == 200) {
                // Convert ms to time and adjust for the timezone
                var t = new Date(), t2 = new Date();
                //t.setTime(responses.Body['Ta0'] * 1000 + (t.getTimezoneOffset() * 60 * 1000));
                t.setTime(responses.Body['Ta0'] * 1000);
                amtdeltatime = t - t2;
                updateSystemStatus();
            }
        }

        var amtdeltatime;
        var amtsysstate;
        var amtlogicalelements; // processSystemVersion
        var amtfeatures = {};
        function processSystemStatus(stack, name, responses, status) {
            // ###BEGIN###{ComputerSelector}
            if (wsstack == null || amtstack != stack) return;
            // ###END###{ComputerSelector}
            // If this computer has no KVM, ignore and continue (Standard Manageability)
            if ((responses['IPS_ScreenConfigurationService'] == undefined) || (responses['IPS_ScreenConfigurationService'].status == 400)) { responses['IPS_ScreenConfigurationService'] = null; }
            if ((responses['IPS_KVMRedirectionSettingData'] == undefined) || (responses['IPS_KVMRedirectionSettingData'].status == 400)) { responses['IPS_KVMRedirectionSettingData'] = null; }
            if ((responses['CIM_KVMRedirectionSAP'] == undefined) || (responses['CIM_KVMRedirectionSAP'].status == 400)) { responses['CIM_KVMRedirectionSAP'] = null; }
            if ((responses['IPS_OptInService'] == undefined) || (responses['IPS_OptInService'].status == 400)) { responses['IPS_OptInService'] = null; }
            if ((responses['AMT_RedirectionService'] != undefined) && (responses['AMT_RedirectionService'].status == 200)) { QV('go13', true); } // Show the terminal
            
            // Reset the status after possible KVM removal
            status = 0;
            for (var i in responses) { if ((responses[i] != null) && (responses[i].status > status)) { status = responses[i].status; } }

            if ((status != 400) && errcheck(status, stack)) return;
            amtsysstate = responses;
            applyDesktopSettings();
            updateSystemStatus();
        }

        // Ask to synchronize the Intel AMT clock
        function syncClock() {
            if (xxdialogMode) return;
            setDialogMode(11, "Sincronizza orologio", 3, syncClockEx, "Sincronizzare l'orologio Intel AMT con questo computer?");
        }

        // Synchronize the Intel AMT clock
        function syncClockEx() {
            amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(function (stack, name, response, status) {
                if (status != 200) { messagebox('', "Impossibile impostare l'ora, status =" + status); return; }
                if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossibile impostare l'ora, errore: " + response.Body['ReturnValueStr']); return; }
                //var now = new Date(), Tm1 = Math.round((now.getTime() - (now.getTimezoneOffset() * 60000)) / 1000);
                var now = new Date(), Tm1 = Math.round(now.getTime() / 1000);
                amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, function () { amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(processSystemTime); });
            });
        }

        // ###BEGIN###{PowerControl}
        var DMTFPowerStates = ['', '', "Accensione", "Sonno leggero", "Sonno profondo", "Ciclo di accensione (soft off)", "Off - Difficile", "Ibernazione (Off soft)", "Soft off", "Ciclo di accensione (Off-hard)", "Ripristino del bus principale", "Diagnostic interrupt (NMI)", "Non applicabile", "Off - Morbido grazioso", "Off - Hard aggraziato", "Ripristino del bus principale aggraziato", "Ciclo di accensione (Off - Soft aggraziato)", "Ciclo di accensione (Off - Hard Graceful)", "Interruzione diagnostica (INIT)"];
        // ###END###{PowerControl}
        function updateSystemStatus() {
            if ((!amtsysstate) || (currentView > 99)) return;

            // System Status Table
            var systemdefense = 0, host, y, x = TableStart(), features = '', gs = amtsysstate['AMT_GeneralSettings'].response;
            // ###BEGIN###{PowerControl}
            var t = '<i>' + "Sconosciuto" + '</i>';
            if ((amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0)) {
                t = DMTFPowerStates[amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState']];
                // If Intel AMT 10+, check OS power saving state.
                if ((amtversion > 9) && (t == "Accensione") && (amtsysstate['IPS_PowerManagementService']) && (amtsysstate['IPS_PowerManagementService'].response) && (amtsysstate['IPS_PowerManagementService'].response['OSPowerSavingState'] == 3)) { t = 'Standby (Connected)'; }
                // ###BEGIN###{Terminal}
                QH('id_p13power', t); // Display the power state on the terminal form
                // ###END###{Terminal}
                // ###BEGIN###{Desktop}
                //if ((desktop.State != 0) && (Q('id_p14power').innerHTML.length > 0) && (Q('id_p14power').innerHTML != t)) { desktop.Stop(); setTimeout(connectDesktop, 150); }
                QH('id_p14power', t); // Display the power state on the desktop form
                // ###END###{Desktop}
            }
            if (gs['PowerSource']) t += [", Connesso", ", A batteria"][gs['PowerSource']];
            x += TableEntry("Energia", addLink(t, 'showPowerActionDlg()'));
            // ###END###{PowerControl}

            host = gs['HostName'];
            y = gs['DomainName'];
            if (y != null && y.length > 0) host += '.' + y;
            if (host.length == 0) { host = ('<i>' + "Nessuna" + '</i>'); } else { host = EscapeHtml(host); }
            x += TableEntry("Nome e dominio", addLinkConditional(host, 'showEditNameDlg()', xxAccountAdminName));
            if (amtstack.amtauth && amtstack.amtauth.uuidStr) {
                x += TableEntry("ID di sistema", amtstack.amtauth.uuidStr);
            } else if (HardwareInventory) {
                x += TableEntry("ID di sistema", guidToStr(HardwareInventory['CIM_ComputerSystemPackage'].response['PlatformGUID'].toLowerCase()));
            }
            if (amtlogicalelements) {
                var mode = '', scs = getItem(amtlogicalelements, 'CreationClassName', 'AMT_SetupAndConfigurationService');
                // ###BEGIN###{!Look-Intel-SBT}
                if ((scs['ProvisioningState'] == 2) && (amtversion > 5)) {
                    mode = " attivato in modalità controllo amministratore (ACM)";
                    if (scs['ProvisioningMode'] == 4) { mode = " attivato in modalità controllo client (CCM)"; systemdefense = 9; }
                }
                // ###END###{!Look-Intel-SBT}

                // ###BEGIN###{Look-Intel-SBT}
                x += TableEntry("Intel&reg; SBT", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Intel-SBT}
                // ###BEGIN###{Look-Intel-SM}
                x += TableEntry("Intel&reg; SM", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Intel-SM}
                // ###BEGIN###{Look-Intel-AMT}
                x += TableEntry("Intel&reg; AMT", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Intel-AMT}
                // ###BEGIN###{Look-Commander}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Commander}
                // ###BEGIN###{Look-ISDU}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-ISDU}
                // ###BEGIN###{Look-BrandedCommander}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-BrandedCommander}
                // ###BEGIN###{Look-Unite}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Unite}
                // ###BEGIN###{Look-MeshCentral}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-MeshCentral}

                // ###BEGIN###{ComputerSelector}
                currentcomputer['ver'] = getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'];
                currentcomputer['pstate'] = scs['ProvisioningState'];
                currentcomputer['pmode'] = scs['ProvisioningMode'];
                currentcomputer['date'] = new Date().toISOString();
                updateComputerDetails();
                // ###BEGIN###{ComputerSelector-Local}
                saveComputers();
                // ###END###{ComputerSelector-Local}
                // ###END###{ComputerSelector}
            }

            // ###BEGIN###{!Mode-MeshCentral2}

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                QH('id_computername', "Computer: " + ((gs['HostName'] == '') ? ('<i>' + "Nessuna" + '</i>') : gs['HostName']) + ", Server: " + meshCentralServer.host);
            } else {
                QH('id_computername', "Computer: " + ((gs['HostName'] == '') ? ('<i>' + "Nessuna" + '</i>') : gs['HostName']));
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QH('id_computername', "Computer: " + ((gs['HostName'] == '') ? ('<i>' + "Nessuna" + '</i>') : gs['HostName']));
            // ###END###{!MeshServerConnect}

            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            if (gs['HostName'] != '') { require('nw.gui').Window.get().title = NW_WindowTitle + ' - ' + gs['HostName']; } else { require('nw.gui').Window.get().title = NW_WindowTitle; }
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{PowerControl}
            if ((amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0)) {
                // Intel AMT power state warning. If computer is not powered on, display a warning in terminal and desktop panels.
                // ###BEGIN###{Terminal}
                QV('id_p13warning2', amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] != 2);
                // ###END###{Terminal}
                // ###BEGIN###{Desktop}
                QV('id_p14warning2', amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] != 2);
                // ###END###{Desktop}
            }
            // ###END###{PowerControl}

            // ###BEGIN###{!Look-Intel-SBT}
            // Intel AMT Features
            if (amtsysstate['AMT_RedirectionService'].status == 200) {
                var redir = amtfeatures[0] = (amtsysstate['AMT_RedirectionService'].response['ListenerEnabled'] == true);
                var sol = amtfeatures[1] = ((amtsysstate['AMT_RedirectionService'].response['EnabledState'] & 2) != 0);
                var ider = amtfeatures[2] = ((amtsysstate['AMT_RedirectionService'].response['EnabledState'] & 1) != 0);
                var kvm = amtfeatures[3] = undefined;
                if ((amtversion > 5) && (amtsysstate['CIM_KVMRedirectionSAP'] != null)) {
                    // ###BEGIN###{Desktop}
                    QV('go14', true); // Desktop
                    // ###END###{Desktop}
                    kvm = amtfeatures[3] = ((amtsysstate['CIM_KVMRedirectionSAP'].response['EnabledState'] == 6 && amtsysstate['CIM_KVMRedirectionSAP'].response['RequestedState'] == 2) || amtsysstate['CIM_KVMRedirectionSAP'].response['EnabledState'] == 2 || amtsysstate['CIM_KVMRedirectionSAP'].response['EnabledState'] == 6);
                }
                if (redir) features += ", Porta di reindirizzamento";
                if (sol) features += ", Seriale su LAN";
                if (ider) features += ", IDE-reindirizzamento";
                if (kvm) features += ", KVM";
                if (features == '') features = '  ' + "Nessuna";
                x += TableEntry("Funzionalità attive", addLinkConditional(features.substring(2), 'showFeaturesDlg()', xxAccountAdminName));
            }

            if ((amtsysstate['IPS_KVMRedirectionSettingData'] != null) && (amtsysstate['IPS_KVMRedirectionSettingData'].response)) {
                var desktopSettings = amtsysstate['IPS_KVMRedirectionSettingData'].response;
                var screenname = "Display principale";
                if ((amtversion > 7) && (desktopSettings['DefaultScreen'] !== undefined) && (desktopSettings['DefaultScreen'] < 255)) { screenname = ["Display principale", "Display secondario", "3 ° display"][desktopSettings['DefaultScreen']]; }
                features = '<span title="' + format("Il display remoto predefinito è {0}", screenname.toLowerCase()) + '">' + screenname + '</span>';
                if (desktopSettings['Is5900PortEnabled'] == true) { features += ", Porta 5900 abilitata"; }
                if (desktopSettings['OptInPolicy'] == true) { features += "," + desktopSettings['OptInPolicyTimeout'] + ' ' + ((desktopSettings['OptInPolicyTimeout'] > 0)?"secondi opt-in":"secondo opt-in"); }
                features += "," + desktopSettings['SessionTimeout'] + " minuto" + ((desktopSettings['SessionTimeout'] > 0) ? 's' : '') + " timeout della sessione";

                // Screen blanking on AMT 10 and higher
                if ((amtversion > 9) && (amtsysstate['IPS_ScreenConfigurationService'] != null)) {
                    var screenBlanking = ((amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState'] & 1) != 0);
                    if (screenBlanking) features += ", Soppressione consentita";
                    // ###BEGIN###{Desktop}
                    QV('id_DeskSBspan', screenBlanking);
                    Q('id_DeskSB').checked = false;
                    // ###END###{Desktop}
                } else {
                    // ###BEGIN###{Desktop}
                    QV('id_DeskSBspan', false);
                    // ###END###{Desktop}
                }

                // ###BEGIN###{Desktop-Settings}
                x += TableEntry("Desktop remoto", addLinkConditional(features, 'showDesktopSettingsDlg()', xxAccountAdminName));
                // ###END###{Desktop-Settings}
                // ###BEGIN###{!Desktop-Settings}
                x += TableEntry("Desktop remoto", features);
                // ###END###{!Desktop-Settings}
            }
            // ###BEGIN###{Terminal}
            QV('id_p13warning1', !redir || !sol); // Show the warning box on top of the terminal if redirection or sol is disabled.
            QV('id_p13warninga', xxAccountAdminName); // If we are not administrator, we can't activate SOL.
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            QV('id_p14warning1', !redir || !kvm); // Show the warning box on top of the remote desktop viewer if redirection or kvm is disabled.
            QV('id_p14warninga', xxAccountAdminName); // If we are not administrator, we can't activate KVM.
            // ###END###{Desktop}

            // Intel AMT user Consent
            if ((amtversion > 5) && (amtsysstate != null && amtsysstate['IPS_OptInService'] != null) && (amtsysstate['IPS_OptInService'].response != undefined)) {
                features = "Stato sconosciuto";
                var optinrequired = amtsysstate['IPS_OptInService'].response['OptInRequired'];
                if (optinrequired == 0) { features = "Non richiesto"; }
                if (optinrequired == 1) { features = "Richiesto solo per KVM"; }
                if (optinrequired == 0xFFFFFFFF) { features = "Sempre richiesto"; }
                if (amtsysstate['IPS_OptInService'].response['CanModifyOptInPolicy'] == true) features = addLinkConditional(features, 'showConsentDlg()', xxAccountAdminName); // If we can modify user consent settings, add the link to do it.
                x += TableEntry("Consenso dell'utente", features);
            }

            // Power Options
            if ((amtsysstate['AMT_BootCapabilities'].response['PlatformErase'] != null) && (amtsysstate['AMT_BootCapabilities'].response['PlatformErase'] > 0) && (amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] != null)) {
                var enabledBootStateStr = { 0: "Sconosciuto", 1: "Altro", 2: "Abilitato", 3: "Disabilitato", 4: "Chiudere", 5: "Non applicabile", 6: "Abilitato ma offline", 7: "In prova", 8: "differite", 9: "quiesce", 10: "Di partenza", 32768: "OCR Disabled", 32769: "OCR Enabled", 32770: "OCR Disabled, RPE Enabled", 32771: "RPE & OCR Enabled" };
                if (amtversion > 15) { enabledBootStateStr[32768] = "OCR & RPE Disabled"; enabledBootStateStr[32769] = "OCR Enabled, RPE Disabled"; }
                var t = enabledBootStateStr[amtsysstate['CIM_BootService'].response['EnabledState']]?enabledBootStateStr[amtsysstate['CIM_BootService'].response['EnabledState']]:"Sconosciuto";
                x += TableEntry("Boot Features", addLinkConditional(t, 'showEnableBootServiceDlg()', xxAccountAdminName));
            }

            // Intel AMT Power policy
            if (AmtSystemPowerSchemes != null) {
                var elementSettings = amtsysstate['CIM_ElementSettingData'].responses;
                for (var i = 0; i < elementSettings.length; i++) {
                    if (elementSettings[i]['SettingData'] && elementSettings[i]['IsCurrent'] == 1 && elementSettings[i]['SettingData']['ReferenceParameters']['ResourceURI'] == 'http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SystemPowerScheme') {
                        // Found the active Intel AMT power scheme
                        var powerguid = elementSettings[i]['SettingData']['ReferenceParameters']['SelectorSet']['Selector'][1]['Value'];
                        // Now find the name of the power schema in the AMT_SystemPowerScheme table
                        for (var j = 0; j < AmtSystemPowerSchemes.length; j++) {
                            if (AmtSystemPowerSchemes[j]['SchemeGUID'] == powerguid) {
                                // Found the power scheme name
                                x += TableEntry("Politica energetica", addLinkConditional(AmtSystemPowerSchemes[j]['Description'].split(':' )[1], 'showPowerPolicyDlg(\"' + powerguid + '\")', xxAccountAdminName));
                            }
                        }
                    }
                }
            }
            // ###END###{!Look-Intel-SBT}

            if (amtdeltatime) { x += TableEntry("Appuntamento", addLinkConditional(new Date(new Date().getTime() + amtdeltatime).toLocaleString(), 'syncClock()', xxAccountAdminName)); }
            var buttons = AddRefreshButton('PullSystemStatus()') + ' ';
            // ###BEGIN###{PowerControl}
            buttons += AddButton("Azioni di potere ...", 'showPowerActionDlg()') + ' ';
            // ###END###{PowerControl}
            // ###BEGIN###{WsmanBrowser}
            // ###BEGIN###{FileSaver}
            buttons += AddButton("Salva stato ...", 'saveEntireAmtState()') + ' ';
            // ###END###{FileSaver}
            // ###END###{WsmanBrowser}
            // ###BEGIN###{Scripting}
            buttons += AddButton("Esegui script ...", 'script_runScriptDlg()') + ' ';
            // ###END###{Scripting}
            x += TableEnd(buttons);

            // Show authentic CSME if present
            if (amtstack.amtauth) { x += '<div style=position:absolute;top:10px;right:20px;cursor:pointer onclick=showAuthCsme()><img src=authcsme.png width=100 height=100 /></div>'; }

            QH('id_TableSysStatus', x);

            // ###BEGIN###{NetworkSettings}
            var x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            x += TableEnd('<div>&nbsp;' + AddRefreshButton('PullSystemStatus(1)')
                // ###BEGIN###{!Mode-LMS}
                + " La modifica delle impostazioni di rete potrebbe rendere questa pagina non disponibile."
                // ###END###{!Mode-LMS}
                // ###BEGIN###{Mode-LMS}
                + " Changing network settings may cause this page to be unavailable for a few seconds."
                // ###END###{Mode-LMS}
            );

            // General settings
            x += '<br><h2>' + "impostazioni generali" + '</h2>';
            x += TableStart();

            // Network state
            // if (gs['AMTNetworkEnabled']) { x += TableEntry("Network state", (gs['AMTNetworkEnabled']==1)?"Enabled":"Disabled"); }

            // Shared FQDN
            var fqdnshare = '';
            if (host != '<i>' + "Nessuna" + '</i>') {
                if (gs['SharedFQDN'] == true) fqdnshare = ", condiviso con il sistema operativo";
                if (gs['SharedFQDN'] == false) fqdnshare = ", diverso dal sistema operativo";
            }
            x += TableEntry("Nome e dominio", addLinkConditional(host + fqdnshare, 'showEditNameDlg(1)', xxAccountAdminName));

            // Dynamic DNS
            var ddns = "Disabilitato";
            if (gs['DDNSUpdateEnabled'] == true) {
                ddns = "Abilitato ciascuno" + gs['DDNSPeriodicUpdateInterval'] + " minuti, TTL è" + gs['DDNSTTL'] + " minuti";
            } else if (gs['DDNSUpdateByDHCPServerEnabled'] == true) {
                ddns = "Aggiornamento dal server DHCP";
            }
            x += TableEntry("DNS dinamico", addLinkConditional(ddns, 'showEditDnsDlg()', xxAccountAdminName));
            x += TableEnd();

            for (var y in amtsysstate['AMT_EthernetPortSettings'].responses) {
                var z = amtsysstate['AMT_EthernetPortSettings'].responses[y];
                if (z['WLANLinkProtectionLevel'] || (y == 1)) { amtwirelessif = y; } // Set the wireless interface, this seems to cover new wireless only computers and older computers with dual interfaces.
                if ((y == 0) && (amtwirelessif != y) && (z['MACAddress'] == '00-00-00-00-00-00')) { continue; } // On computers with only wireless, the wired interface will have a null MAC, skip it.
                if (y == 0) systemdefense++;
                x += '<br><h2>' + ((amtwirelessif == y)?"Interfaccia wireless":"Interfaccia cablata") + '</h2>';
                x += TableStart();

                /*
                var lp = [], linkpolicy = MakeToArray(z['LinkPolicy']);
                for (var p in linkpolicy) {
                    var ap = linkpolicy[p];
                    if (ap == 1) lp.push("S0/AC");
                    if (ap == 14) lp.push("Sx/AC");
                    if (ap == 16) lp.push("S0/DC");
                    if (ap == 224) lp.push("Sx/DC");
                }
                x += TableEntry("Link state", (z['LinkIsUp'] == true?"Link is up":"Link is down") + ", available in " + lp.join(', '));
                */
                x += TableEntry("Stato di collegamento", (z['LinkIsUp'] == true?"Il collegamento è attivo":"Il link non è attivo"));
                if (z['LinkPolicy']) {
                    z['LinkPolicy'] = MakeToArray(z['LinkPolicy']);
                    var linkPolicyStr = [];
                    for (var i in z['LinkPolicy']) {
                        if (z['LinkPolicy'][i] == 1) { linkPolicyStr.push("S0 / AC"); }
                        if (z['LinkPolicy'][i] == 14) { linkPolicyStr.push("Sx / AC"); }
                        if (z['LinkPolicy'][i] == 16) { linkPolicyStr.push("S0 / DC"); }
                        if (z['LinkPolicy'][i] == 224) { linkPolicyStr.push("Sx / DC"); }
                    }
                    if (linkPolicyStr.length == 0) { linkPolicyStr.push(''); }
                    x += TableEntry("Politica di collegamento", addLinkConditional((linkPolicyStr.length == 0) ? "Non disponibile" : "Disponibili in: " + linkPolicyStr.join(', '), 'showLinkPolicyDlg(' + y + ')', xxAccountAdminName));
                }
                if (z['MACAddress'] != '00-00-00-00-00-00') { x += TableEntry("Indirizzo MAC", z['MACAddress']); }

                // ###BEGIN###{Wireless}
                if ((amtwirelessif == y) && xxWireless && xxWireless['CIM_WiFiPortCapabilities'].response) {
                    // Start and state
                    x += TableEntry("Stato", addLinkConditional(xxWifiState[xxWireless['CIM_WiFiPort'].response['EnabledState']], 'showWifiStateDlg()', xxAccountAdminName));
        
                    /* This is not that useful
                    // Capabilities
                    var s = '', sc = xxWireless['CIM_WiFiPortCapabilities'].response, supportedTypes = sc['SupportedPortTypes'];
                    for (i in supportedTypes) { s += ", 802.11" + "abgn"[supportedTypes[i] - 70]; }
                    x += TableEntry("Capabilites", s.substring(2));
                    */

                    // Current radio state
                    s = xxWireless['CIM_WiFiEndpoint'].response['LANID'];
                    x += TableEntry("Stato radio", xxRadioState[xxWireless['CIM_WiFiEndpoint'].response['EnabledState']] + ", SSID: " + (s ? s : ('<i>' + "Nessuna" + '</i>')));

                    // Current local profile synchronization
                    if (xxWireless['AMT_WiFiPortConfigurationService'] && xxWireless['AMT_WiFiPortConfigurationService'].response && (typeof xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 'number')) {
                        x += TableEntry("Local WIFI Profile Sync", addLinkConditional(((xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 1) ? "Abilitato" : "Disabilitato"), 'showWifiSyncDlg(' + y + ')', xxAccountAdminName));
                    }
                    // CSME UEFI Wifi profile sharing, check if it is enabled in boot setting and it is not null at AMT_WiFiPortConfigrationService
                    if (amtsysstate['AMT_BootCapabilities'].response['UEFIWiFiCoExistenceAndProfileShare'] != null && amtsysstate['AMT_BootCapabilities'].response['UEFIWiFiCoExistenceAndProfileShare'] == true
                        && xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled']!=null) {
                            x += TableEntry("UEFI WiFi CoEx Profile sharing", addLinkConditional(xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled']==1? "Abilitato":"Disabilitato", 'showUefiWifiCoExDlg()', xxAccountAdminName));
                     } else {
                        x += TableEntry("UEFI WiFi CoEx Profile sharing", "Unavailable");
                     }
                }
                // ###END###{Wireless}

                if (amtwirelessif != y) {
                    // Things that are specific to the wired interface
                    x += TableEntry("Rispondi al ping", addLinkConditional(["Disabilitato", "Risposta ICMP", "Risposta RMCP", "Risposta ICMP e RMCP"][gs['PingResponseEnabled'] + (gs['RmcpPingResponseEnabled'] << 1)], 'showPingActionDlg()', xxAccountAdminName));
                    // ###BEGIN###{NetAuth}
                    // 802.1x
                    var netAuthProtocols = ['EAP-TLS', 'EAP-TTLS/MSCHAPv2', 'PEAPv0/EAP-MSCHAPv2', 'PEAPv1/EAP-GTC', 'EAP-FAST/MSCHAPv2', 'EAP-FAST/GTC', 'EAP-FAST/TLS'], netAuthStr = "Disabilitato";
                    if (amtsysstate['AMT_8021XProfile'].responses.Body['Enabled']) { netAuthStr = "Abilitato," + netAuthProtocols[amtsysstate['AMT_8021XProfile'].responses.Body['AuthenticationProtocol']]; }
                    x += TableEntry("802.1x", addLinkConditional(netAuthStr, 'editNetAuthProfile()', xxAccountAdminName));
                    // ###END###{NetAuth}
                    var ipStateString = z['DHCPEnabled'] == true ? "Automatico tramite server DHCP" : "Indirizzo IP statico";
                    if (z['IpSyncEnabled'] == true) { ipStateString += ', IP sync with OS'; }
                    x += TableEntry("Stato IPv4", addLinkConditional(ipStateString, 'showIPSetupDlg()', xxAccountAdminName));
                }

                // Display IPv4 current settings
                x += TableEntry("Indirizzo IPv4", isIpAddress(z['IPAddress'],"Nessuna"));
                if (isIpAddress(z['DefaultGateway'])) { x += TableEntry("Gateway / maschera IPv4", z['DefaultGateway'] + ' / ' + isIpAddress(z['SubnetMask'],"Nessuna")); }
                
                var dns = z['PrimaryDNS'];
                if (isIpAddress(dns)) {
                    if (z['SecondaryDNS']) dns += ' / ' + z['SecondaryDNS'];
                    x += TableEntry("Server dei nomi di dominio IPv4", dns);
                }

                if ((amtsysstate['IPS_IPv6PortSettings'].status == 200) && (amtversion > 5)) {
                    // Check if IPv6 is enabled for this interface
                    var zz = amtsysstate['IPS_IPv6PortSettings'].responses[y];
                    var ipv6state = "Disabilitato", ipv6, ipv6manual, elementSettings = amtsysstate['CIM_ElementSettingData'].responses;
                    for (var i = 0; i < elementSettings.length; i++) {
                        if (elementSettings[i]['SettingData'] && elementSettings[i]['SettingData']['ReferenceParameters']['SelectorSet']['Selector']['Value'] == 'Intel(r) IPS IPv6 Settings ' + y) {
                            ipv6 = (elementSettings[i]['IsCurrent'] == 1);
                        }
                    }

                    // Check if manual addresses have been added
                    if (ipv6 == true) { 
                        ipv6manual = isIpAddress(zz['IPv6Address']) || isIpAddress(zz['DefaultRouter']) || isIpAddress(zz['PrimaryDNS']) || isIpAddress(zz['SecondaryDNS']);
                        ipv6state = (ipv6manual ? "Indirizzi abilitati, automatici e manuali" : "Abilitato, indirizzi automatici");
                    }

                    // Display IPv6 current settings
                    x += TableEntry("Stato IPv6", addLinkConditional(ipv6state, 'showIPv6StateDlg(' + y + ',' + ipv6 + ')', xxAccountAdminName));
                    if (ipv6 == true) {
                        if (zz['CurrentAddressInfo'] && zz['CurrentAddressInfo'].length > 0) {
                            zz['CurrentAddressInfo'] = MakeToArray(zz['CurrentAddressInfo']); // Because our WSMAN stack does not know if this is a array, we need to make it an array if it contains 1 element.
                            ipv6addr = '';
                            for (var i = 0; i < zz['CurrentAddressInfo'].length; i++) { if (ipv6addr.length > 0) ipv6addr += ","; ipv6addr += zz['CurrentAddressInfo'][i].split(',')[0]; }
                            x += TableEntry("Indirizzo IPv6", addLink(ipv6addr, 'showIPv6AddrDlg(' + y + ',\"' + zz['CurrentAddressInfo'] + '\")'));
                        } else {
                            x += TableEntry("Indirizzo IPv6", "Nessuna");
                        }
                        if (isIpAddress(zz['CurrentDefaultRouter'])) { x += TableEntry("Router predefinito IPv6", zz['CurrentDefaultRouter']); }
                        if (isIpAddress(zz['CurrentPrimaryDNS'])) {
                            var dns = zz['CurrentPrimaryDNS'];
                            if (isIpAddress(zz['CurrentSecondaryDNS'])) dns += ' / ' + zz['CurrentSecondaryDNS'];
                            x += TableEntry("Server dei nomi di dominio IPv6", dns);
                        }
                    }
                }

                x += TableEnd();
            }

            // Only do more WSMAN if we need it
            if ((urlvars['kvmonly'] != 1) && (fullscreenonly == false)) {
                // ###BEGIN###{Wireless}
                // If there is a wireless interface, get the data for it. If not, show that there is not.
                if (amtwirelessif != -1) { if ((amtFirstPull & 2) == 0) PullWireless(); }
                // ###END###{Wireless}
                QH('id_TableNetworkSettingsSpan', x);
                // ###END###{NetworkSettings}

                // ###BEGIN###{SystemDefense}
                // If in ACM mode and we have a wired interface, pull System Defense information
                if ((systemdefense == 1) && ((amtFirstPull & 4) == 0)) PullSystemDefense();
                // ###END###{SystemDefense}

                // ###BEGIN###{Storage}
                if (((amtFirstPull & 8) == 0) && (amtversion > 11 || ((amtversion == 11) && (amtversionmin > 5)))) { PullStorage(); }
                // ###END###{Storage}
            }

            if (currentView == 0) go(1, 1); // If we are at the loading screen, most to System Status screen
        }

        function isIpAddress(t, x) { return (t && t != null && t.length > 0 && t != '::' && t != '::0')?t:x; }

        function showLinkPolicyDlg(y) {
            if (xxdialogMode) return;
            var z = amtsysstate['AMT_EthernetPortSettings'].responses[y], s = '';
            s += '<label><input type=checkbox id=d11p1 value=1 ' + ((z['LinkPolicy'].indexOf(1) >= 0) ? 'checked' : '') + '>Available in S0/AC - Powered on & plugged in</label><br>';
            s += '<label><input type=checkbox id=d11p2 value=14 ' + ((z['LinkPolicy'].indexOf(14) >= 0) ? 'checked' : '') + '>Available in Sx/AC - Sleeping & plugged in</label><br>';
            s += '<label><input type=checkbox id=d11p3 value=16 ' + ((z['LinkPolicy'].indexOf(16) >= 0) ? 'checked' : '') + '>Available in S0/DC - Powered on & on battery</label><br>';
            s += '<label><input type=checkbox id=d11p4 value=224 ' + ((z['LinkPolicy'].indexOf(224) >= 0) ? 'checked' : '') + '>Available in Sx/DC - Sleeping & on battery</label><br>';
            setDialogMode(11, "Politica sui collegamenti", 3, showLinkPolicyDlgEx, s, y);
        }

        function showLinkPolicyDlgEx(b, y) {
            var x = Clone(amtsysstate['AMT_EthernetPortSettings'].responses[y]);
            if (x['DHCPEnabled']) {
                delete x['IPAddress'];
                delete x['SubnetMask'];
                delete x['DefaultGateway'];
                delete x['PrimaryDNS'];
                delete x['SecondaryDNS'];
            }
            x['LinkPolicy'] = [];
            if (Q('d11p1').checked) { x['LinkPolicy'].push(1); }
            if (Q('d11p2').checked) { x['LinkPolicy'].push(14); }
            if (Q('d11p3').checked) { x['LinkPolicy'].push(16); }
            if (Q('d11p4').checked) { x['LinkPolicy'].push(224); }
            amtstack.Put('AMT_EthernetPortSettings', x, showLinkPolicyDlgExDone, 0, 1, x);
        }

        function showLinkPolicyDlgExDone(stack, name, response, status) {
            if (status == 200) {
                amtsysstate = undefined;
                PullSystemStatus();
            } else {
                messagebox("Politica sui collegamenti", format("Impossibile impostare la nuova politica di collegamento, errore {0}", status));
            }
        }

        function showAuthCsme() {
            if (xxdialogMode) return;
            var x = '<div style=margin-top:8px>' + "Intel&reg; AMT supports authentic CSME feature, however MeshCommander cannot verify the authenticity yet." + '</div><hr style=margin-top:8px;margin-bottom:8px;height:2px;border-width:0;color:gray;background-color:gray />';
            x += addHtmlValue("FW Version", amtstack.amtauth.FWVersion);
            x += addHtmlValue("FQDN", amtstack.amtauth.FQDN ? amtstack.amtauth.FQDN : ('<i>' + "Nessuna" + '</i>'));
            x += '<hr style=margin-top:8px;margin-bottom:8px;height:2px;border-width:0;color:gray;background-color:gray /><div style=max-height:200px;overflow-y:auto><table>';
            for (var i in amtstack.amtauth.Certificates) {
                var cert = amtstack.amtauth.Certificates[i];
                x += '<tr><td style=width:32px;vertical-align:top><img src=images-commander/cert1.png height=32 width=32 />';
                x += '<td style=padding-bottom:6px><b>' + EscapeHtml(cert.subject.getField('CN').value) + ((cert.xTrusted === true) ? ', <span style=color:#080>' + "di fiducia" + '</span>' : '') + '</b><br />';
                if (cert.subject.getField('OU')) { x += EscapeHtml(cert.subject.getField('OU').value) + '<br />'; }
                // ###BEGIN###{FileSaver}
                x += amtstack.amtauth.CertificatesDer[i].length + " byte," + '<a style=cursor:pointer;color:blue onclick=downloadAuthCert(' + i + ')>' + "Scarica" + '</a>';
                if (cert.xCrl) { x += '<br />' + "CRL " + cert.xCrl.length + " byte," + '<a style=cursor:pointer;color:blue onclick=downloadCertCrl(' + i + ')>' + "Scarica" + '</a>'; }
                // ###END###{FileSaver}
                // ###BEGIN###{!FileSaver}
                x += amtstack.amtauth.CertificatesDer[i].length + " byte";
                if (cert.xCrl) { x += '<br />' + "CRL " + cert.xCrl.length + " byte"; }
                // ###END###{!FileSaver}
            }
            x += '</table><div>';
            setDialogMode(11, "Authentic CSME", 1, null, x);
        }

        // ###BEGIN###{FileSaver}
        function downloadCertCrl(h) {
            h = parseInt(h);
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(amtstack.amtauth.Certificates[h].xCrl), amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.crl');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.crl');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, amtstack.amtauth.Certificates[h].xCrl, 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function downloadAuthCert(h) {
            h = parseInt(h);
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(amtstack.amtauth.CertificatesDer[h]), amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.cer');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, amtstack.amtauth.CertificatesDer[h], 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

// ###BEGIN###{WsmanBrowser}
// ###BEGIN###{FileSaver}
        var IntelAmtEntireState;
        var IntelAmtEntireStateCalls;
        function saveEntireAmtState() {
            if (xxdialogMode) return;
            var n = '', d = new Date();
            if (amtsysstate) { n = '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
            n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);;
            idx_d19savestatefilename.value = 'amtstate' + n + '.json';
            setDialogMode(19, "Salva l'intero stato Intel&reg; AMT", 3, saveEntireAmtStateOk);
        }

        function saveEntireAmtStateOk() {
            IntelAmtEntireState = { 'webappversion':version,'localtime':Date(),'utctime':new Date().toUTCString(),'isotime':new Date().toISOString() };
            QH('id_dialogMessage', 'Fetching entire state, please wait...');
            setDialogMode(1, "Salva l'intero stato Intel&reg; AMT", 0, null);

            // Fetch everything!
            IntelAmtEntireStateCalls = 3;
            amtstack.BatchEnum(null, AllWsman, saveEntireAmtStateOk2, null, true);
            amtstack.GetAuditLog(saveEntireAmtStateOk3);
            amtstack.GetMessageLog(saveEntireAmtStateOk4);
        }

        function saveEntireAmtStateOk2(stack, name, responses, status) { IntelAmtEntireState['wsmanenums'] = responses; saveEntireAmtStateDone(); }
        function saveEntireAmtStateOk3(stack, messages) { IntelAmtEntireState['auditlog'] = messages; saveEntireAmtStateDone(); }
        function saveEntireAmtStateOk4(stack, messages) { IntelAmtEntireState['eventlog'] = messages; saveEntireAmtStateDone(); }

        function saveEntireAmtStateDone() {
            if (--IntelAmtEntireStateCalls != 0) return;
            setDialogMode();
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(JSON.stringify(IntelAmtEntireState, null, '  ').replace(/\n/g, '\r\n')), idx_d19savestatefilename.value);
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', idx_d19savestatefilename.value);
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, JSON.stringify(IntelAmtEntireState, null, '  ').replace(/\n/g, '\r\n'), function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
// ###END###{FileSaver}
// ###END###{WsmanBrowser}

// ###BEGIN###{Desktop-Settings}

        function showDesktopSettingsDlg() {
            if (xxdialogMode) return;
            var desktopSettings = amtsysstate['IPS_KVMRedirectionSettingData'].response;
            var x = '<div style=text-align:left>';
            x += '<div style=height:26px;margin-top:4px><select id=subddisplay style=float:right;width:200px><option value=0>' + "Display principale" + '</option><option value=1>' + "Display secondario" + '</option>';
            if (amtversion > 9) { x += '<option value=2>' + "3 ° display" + '</option>'; }
            x += '</select><div style=padding-top:4px>' + "Visualizzazione predefinita" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=subsessiontimeout style=float:right;width:200px maxlength=5 onkeypress="return numbersOnly(event)"><div style=padding-top:4px>' + "Timeout della sessione (minuti)" + '</div></div>';
            if (desktopSettings['OptInPolicy'] == true) { x += '<div style=height:26px;margin-top:4px><input id=suboptintimeout style=float:right;width:200px maxlength=5 onkeypress="return numbersOnly(event)"><div style=padding-top:4px>' + "Timeout di attivazione (secondi)" + '</div></div>'; }
            x += '<div style=height:26px;margin-top:4px><select id=subdlegacy style=float:right;width:200px onchange=showDesktopSettingsDlgUpdate()><option value=0>' + "Disabilitato, consigliato" + '</option><option value=1>' + "Visualizzatori KVM legacy abilitati" + '</option></select><div style=padding-top:4px>' + "Porta 5900" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=subspassx><input id=subspass type=password autocomplete=off style=float:right;width:200px maxlength=8 onkeyup=showDesktopSettingsDlgUpdate()><div style=padding-top:4px>' + "5900 password (8 caratteri)" + '</div></div>';
            if ((amtversion > 9) && (amtsysstate['IPS_ScreenConfigurationService'] != null)) { x += '<div style=height:26px;margin-top:4px><select id=subsb style=float:right;width:200px onchange=showDesktopSettingsDlgUpdate()><option value=0>' + "Disabilitato" + '</option><option value=1>' + "Abilitato" + '</option></select><div style=padding-top:4px title="' + "Questa funzione non è spesso supportata" + '">' + "Oscuramento dello schermo" + '</div></div>'; }
            x += '</div>';
            setDialogMode(11, "Impostazioni desktop remoto", 3, showDesktopSettingsDlgOk, x);
            Q('subddisplay').value = desktopSettings['DefaultScreen'];
            Q('subsessiontimeout').value = desktopSettings['SessionTimeout'];
            if (desktopSettings['OptInPolicy'] == true) { Q('suboptintimeout').value = desktopSettings['OptInPolicyTimeout']; }
            Q('subdlegacy').value = ((desktopSettings['Is5900PortEnabled'] == true) ? 1 : 0);
            if ((amtversion > 9) && (amtsysstate['IPS_ScreenConfigurationService'] != null)) { Q('subsb').value = amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState']; }
            showDesktopSettingsDlgUpdate();
        }

        function showDesktopSettingsDlgUpdate() {
            QV('subspassx', (Q('subdlegacy').value == 1));
            var ok = ((Q('subdlegacy').value == 0) || (Q('subspass').value.length == 8) || (Q('subspass').value.length == 0)) && (Q('subsessiontimeout').value.length > 0);
            if ((amtsysstate['IPS_KVMRedirectionSettingData'].response['OptInPolicy'] == true) && (Q('suboptintimeout').value.length == 0)) { ok = false; }
            QE('idx_dlgOkButton', ok);
        }

        function showDesktopSettingsDlgOk() {
            var x = Clone(amtsysstate['IPS_KVMRedirectionSettingData'].response);
            x['DefaultScreen'] = Q('subddisplay').value
            x['SessionTimeout'] = Q('subsessiontimeout').value;
            x['Is5900PortEnabled'] = (Q('subdlegacy').value == 1);
            if (x['OptInPolicy'] == true) { x['OptInPolicyTimeout'] = Q('suboptintimeout').value; }
            if (x['Is5900PortEnabled'] == true) { x['RFBPassword'] = Q('subspass').value; }
            amtstack.Put('IPS_KVMRedirectionSettingData', x, showDesktopSettingsDlgOk2);

            // Screen blanking
            var y = Clone(amtsysstate['IPS_ScreenConfigurationService'].response);
            y['EnabledState'] = parseInt(Q('subsb').value);
            amtstack.Put('IPS_ScreenConfigurationService', y, showDesktopSettingsDlgOk3);
        }

        function showDesktopSettingsDlgOk2(stack, name, responses, status) {
            if (status == 200) PullSystemStatus(); else messagebox("Impostazioni desktop remoto", format("Errore {0}, impossibile impostare valori.", status));
        }

        function showDesktopSettingsDlgOk3(stack, name, response, status) {
            if (status != 200) { messagebox("Errore", format("Il blanking dello schermo non può essere impostato, il blanking potrebbe non essere supportato su questo sistema ({0}).", status)); return; }
            amtstack.Get('IPS_ScreenConfigurationService', function (stack, name, response, status) {
                if (status == 200) { amtsysstate['IPS_ScreenConfigurationService'].response = response.Body; updateSystemStatus(); }
            }, 0, 1);
        }

// ###END###{Desktop-Settings}

// ###BEGIN###{EventLog}

        //
        // EVENT LOG PANEL
        //

        function PullEventLog(button) {
            if (button == 1 && xxdialogMode) return;
            amtFirstPull |= 16;
            amtstack.Enum('AMT_MessageLog', processMessageLog0);
            amtstack.GetMessageLog(processMessageLog1);
        }

        var processMessageLog0responses = null;
        function processMessageLog0(stack, name, responses, status) {
            if (status != 200) return;
            if (status) QV('go6', true); // Show event log left panel option
            if (responses) processMessageLog0responses = responses;
            var fr = '', x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            if (processMessageLog0responses != null) { fr = ((processMessageLog0responses[0]['IsFrozen'] == true) ? AddButton("Registro non congelato", 'FreezeLog(0)') : AddButton("Congela registro", 'FreezeLog(1)')); }

            // ###BEGIN###{!FileSaver}
            x += TableEnd('<div style=float:right><input id=eventFilter placeholder="' + "Filtro" + '" style=margin:4px onkeyup=eventFilter()>&nbsp;</div><div>&nbsp;' + AddRefreshButton('PullEventLog(1)') + AddButton("Pulisci il registro", 'ClearLog()') + fr);
            // ###END###{!FileSaver}
            // ###BEGIN###{FileSaver}
            x += TableEnd('<div style=float:right><input id=eventFilter placeholder="' + "Filtro" + '" style=margin:4px onkeyup=eventFilter()>&nbsp;</div><div>&nbsp;' + AddRefreshButton('PullEventLog(1)') + AddButton("Pulisci il registro", 'ClearLog()') + AddButton("Salva...", 'SaveEventLog()') + fr);
            // ###END###{FileSaver}
            QH('id_TableEventLog', x + '<br>');
        }

        // ###BEGIN###{FileSaver}
        function SaveEventLog() {
            if (xxdialogMode || eventmessages == null) return;
            SaveJsonFile('IntelAmtEventlog', 'events', 'Intel AMT Event Log', eventmessages);
        }
        // ###END###{FileSaver}

        var eventmessages = null;
        function processMessageLog1(stack, messages) {
            eventmessages = messages;
            var i, y = 0, x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=80px><p><td><td><td>';
            x += '<tr><td class=r1 style=width:90px><b>&nbsp;&nbsp;Event</b><td class=r1 style=width:110px><b>Time</b><td class=r1 style=width:160px><b>' + "fonte" + '</b><td class=r1><b>' + "Descrizione" + '</b>';
            for (i in messages) {
                y++;
                var icon = 1, m = messages[i];
                if (m['EventSeverity'] >= 8) { icon = 2; } if (m['EventSeverity'] >= 16) { icon = 3; }
                x += '<tr id=xamtevent' + i + ' class=r3 onclick=showEventDetails(' + i + ')><td class=r1><p><div class=icon' + icon + ' style=display:block;float:left;margin-left:5px;margin-right:5px></div>' + (parseInt(i) + 1) + '<td class=r1 title="' + m['Time'].toLocaleString() + '">' + m['Time'].toLocaleDateString('en', { year: 'numeric', month: '2-digit', day: 'numeric' }) + '<br>' + m['Time'].toLocaleTimeString('en', { hour:'2-digit', minute:'2-digit', second:'2-digit' }) + '<td class=r1>' + m['EntityStr'].replace('(r)', '&reg;') + '<td class=r1>' + m['Desc'];
            }
            x += TableEnd(y == 0 ? '&nbsp;' : '');
            QH('id_TableEventLog2', x + '<br>');
            processMessageLog0();
        }

        function FreezeLog(x) { if (!xxdialogMode) { amtstack.AMT_MessageLog_FreezeLog(x, function () { amtstack.Enum('AMT_MessageLog', processMessageLog0); }) } }
        function ClearLog(x) { if (!xxdialogMode) { QH('id_dialogMessage', "Cancella registro eventi?"); setDialogMode(1, "Registro eventi", 3, ClearLogEx); } }
        function ClearLogEx() { amtstack.AMT_MessageLog_ClearLog(function (stack, name, responses, status) { if (status != 200) messagebox("Registro eventi", "Impossibile cancellare, errore: " + status); else PullEventLog(); }) }

        function showEventDetails(h) {
            if (xxdialogMode) return;
            var m = eventmessages[h];
            var x = '<div style=text-align:left>';
            x += addHtmlValue("Tempo", m['Time'].toLocaleString());
            x += addHtmlValue("fonte", m['EntityStr'].replace('(r)', '&reg;'));
            x += addHtmlValue("Descrizione", m['Desc']);
            x += MoreStart();
            x += addHtmlValue("Indirizzo dispositivo", m['DeviceAddress']);
            x += addHtmlValue("Entità", m['Entity']);
            x += addHtmlValue("Istanza dell'entità", m['EntityInstance']);
            var e = '';
            for (var i in m['EventData']) { if (e.length > 0) e +=','; e += m['EventData'][i]; }
            x += addHtmlValue("Dati", e);
            x += addHtmlValue("Compensare", m['EventOffset']);
            x += addHtmlValue("Tipo di sensore", m['EventSensorType']);
            x += addHtmlValue("Gravità", m['EventSeverity']);
            x += addHtmlValue("Tipo di fonte", m['EventSourceType']);
            x += addHtmlValue("genere", m['EventType']);
            x += addHtmlValue("Numero del sensore", m['SensorNumber']);
            x += MoreEnd();
            x += '</div>';
            messagebox(format("Dettagli evento n. {0}", h + 1), x);
        }

        function eventFilter() {
            var filter = Q('eventFilter').value.toLowerCase();
            for (var w in eventmessages) { QV('xamtevent' + w, filter == '' || eventmessages[w]['Desc'].toLowerCase().indexOf(filter) >= 0 || eventmessages[w]['EntityStr'].toLowerCase().indexOf(filter) >= 0); }
        }

// ###END###{EventLog}

// ###BEGIN###{EventSubscriptions}

        //
        // EVENT SUBSCRIPTION PANEL
        //

        var subscriptionsFilters = null; // List of event filters
        var subscriptionsListeners = null; // List of subscribers

        function PullEventSubscriptions() {
            if (subscriptionsFilters == null) { amtstack.Enum('CIM_FilterCollection', processEventSubscriptions0); }
            amtstack.BatchEnum(null, ['CIM_ListenerDestination', 'CIM_FilterCollectionSubscription'], processEventSubscriptions1);
        }

        function processEventSubscriptions0(stack, name, responses, status) {
            if (status == 408 || status == 400) return;
            if (status && errcheck(status, stack)) return;
            subscriptionsFilters = responses;
        }

        function processEventSubscriptions1(stack, name, responses, status) {
            if (status == 408 || status == 400) return;
            if (status && errcheck(status, stack)) return;
            if (status) QV('go22', true); // Show event subscription left panel option
            if (responses) subscriptionsListeners = responses;
            var c= 0, x = TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gestisci gli abbonati agli eventi." + '<br><br>';
            for (var i in subscriptionsListeners['CIM_ListenerDestination']['responses']) {
                var f = subscriptionsListeners['CIM_FilterCollectionSubscription']['responses'][i]['Filter']['ReferenceParameters']['SelectorSet']['Selector']['Value'].replace('(r)', '&reg;');
                var r = subscriptionsListeners['CIM_ListenerDestination']['responses'][i];
                x += '<div class=itemBar onclick="showSubscriptionDetails(' + i + ')"><div style=float:right></div><div style=padding-top:3px;overflow-x:hidden title="' + f + ' - ' + r['Destination'] + '"><b>' + f + '</b> - ' + r['Destination'] + '</div><div style=padding-top:3px></div></div>';
                c++;
            }
            if (c == 0) x += ('<div style=padding-left:15px><br><i>' + "Nessun abbonamento trovato." + '</i></div><br>');
            var y = '<div>&nbsp;' + AddRefreshButton('PullEventSubscriptions()');
            if (xxAccountAdminName) y += AddButton("Nuovo abbonamento", 'newSubscriptionButton()');
            x += '<br><td class=r1>' + TableEnd(y + '</div>');
            QH('id_TableEventSubscriptions', x);
        }

        var subscriptionDeliveryModes = { 2:"Spingere", 3:"Spingere con ACK", 4:"eventi", 5:"Tirare" };
        function showSubscriptionDetails(h) {
            if (xxdialogMode) return;
            var f = subscriptionsListeners['CIM_FilterCollectionSubscription']['responses'][h]['Filter']['ReferenceParameters']['SelectorSet']['Selector']['Value'].replace('(r)', '&reg;');
            var r = subscriptionsListeners['CIM_ListenerDestination']['responses'][h];
            var x = '<div style=text-align:left>';
            x += addHtmlValue("Destinazione", r['Destination']);
            x += addHtmlValue("Filtro", f);
            x += addHtmlValue("Modalità di consegna", subscriptionDeliveryModes[r['DeliveryMode']]);
            x += '</div>';
            setDialogMode(11, "Sottoscrizione" + (h + 1), xxAccountAdminName?5:1, deleteSubscriptionButton, x, h);
        }

        function deleteSubscriptionButton(button, h) {
            if (button != 2) return;
            var name = subscriptionsListeners['CIM_ListenerDestination']['responses'][h]['Name'];
            var filter = subscriptionsListeners['CIM_FilterCollectionSubscription']['responses'][h]['Filter']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
            amtstack.UnSubscribe('CIM_FilterCollectionSubscription', PullEventSubscriptions, null, 1, {'Filter':'<a:EndpointReference><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_FilterCollection</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + filter + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference>', 'Handler':'<a:EndpointReference><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ListenerDestinationWSManagement</w:ResourceURI><w:SelectorSet><w:Selector Name="CreationClassName">CIM_ListenerDestinationWSMAN</w:Selector><w:Selector Name="Name">' + name + '</w:Selector><w:Selector Name="SystemCreationClassName">CIM_ComputerSystem</w:Selector><w:Selector Name="SystemName">Intel(r) AMT</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference>'});
        }

        function newSubscriptionButton() {
            if (xxdialogMode || (subscriptionsFilters == null)) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><select id=subtype style=float:right;width:260px><option value=Push>' + "Spingere" + '</option><option value=PushWithAck>' + "Spingere con ACK" + '</option></select><div style=padding-top:4px>' + "genere" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=subfilter style=float:right;width:260px>';
            for (var i in subscriptionsFilters) { x += '<option value="' + subscriptionsFilters[i]['InstanceID'] + '">' + subscriptionsFilters[i]['CollectionName'].substring(13) + '</option>'; }
            x += '</select><div style=padding-top:4px>' + "Filtro" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=suburl style=float:right;width:260px maxlength=253 onkeyup=newSubscriptionUpdate() value="http://"><div style=padding-top:4px>' + "URL" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=subauth style=float:right;width:260px onchange=newSubscriptionUpdate()><option value=0>' + "Nessuna" + '</option><option value=1>' + "digerire" + '</option></select><div style=padding-top:4px>' + "Autenticazione" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=subxuser><input id=subuser style=float:right;width:260px maxlength=32 onkeyup=newSubscriptionUpdate()><div style=padding-top:4px>' + "Nome utente" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=subxpass><input id=subpass style=float:right;width:260px maxlength=32 onkeyup=newSubscriptionUpdate()><div style=padding-top:4px>' + "Parola d'ordine" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=subargs style=float:right;width:260px maxlength=128><div style=padding-top:4px>' + "argomenti" + '</div></div>';
            setDialogMode(11, "Aggiungi abbonamento evento", 3, newSubscriptionButtonOk, x);
            newSubscriptionUpdate();
        }

        function newSubscriptionUpdate() {
            QE('idx_dlgOkButton', ((Q('suburl').value.length > 0) && (Q('suburl').value.startsWith('http://')) && ((Q('subauth').value == 0) || ((Q('subuser').value.length > 0) && (Q('subpass').value.length > 0)))));
            QV('subxuser', Q('subauth').value == 1);
            QV('subxpass', Q('subauth').value == 1);
        }

        function newSubscriptionButtonOk() {
            var user = (Q('subuser').value.length == 0)?undefined:Q('subuser').value, pass = (Q('subpass').value.length == 0)?undefined:Q('subpass').value;
            amtstack.Subscribe('CIM_FilterCollection', Q('subtype').value, Q('suburl').value, newSubscriptionButtonOk2, null, 1, { 'InstanceID' : Q('subfilter').value }, (Q('subargs').value.length > 0)?Q('subargs').value:null, user, pass);
        }

        function newSubscriptionButtonOk2(stack, name, responses, status) {
            if (status == 200) { PullEventSubscriptions(); }
        }

// ###END###{EventSubscriptions}

// ###BEGIN###{AuditLog}

        //
        // AUDIT LOG PANEL
        //

        function PullAuditLog(button) {
            if (button == 1 && xxdialogMode) return;
            amtFirstPull |= 32;
            amtstack.Enum('AMT_AuditLog', processAuditLog0);
        }

        var auditLog = null;
        var auditLogEnabledStates = ["Sconosciuto", "Altro", "Abilitato", "Disabilitato", "Chiudere", "Non applicabile", "Abilitato ma offline", "In prova", "differite", "quiesce", "Di partenza"];

        function processAuditLog0(stack, name, responses, status) {
            if (status == 200) {
                QV('go15', true); // Show audit log left panel option

                var r = responses[0]['AuditState'];
                var auditstate = (r & 0x01) ? "Disabilitato" : "Abilitato";
                if (r & 0x02) auditstate += ", Bloccato";
                if (r & 0x04) auditstate += ", Quasi pieno";
                if (r & 0x08) auditstate += ", Pieno";
                if (r & 0x10) auditstate += ", NoKey";

                var x = '<h1>' + "Impostazioni registro di controllo" + '</h1>' + TableStart();
                x += TableEntry("Stato", auditstate);
                x += TableEntry("Conservazione", responses[0]['CurrentNumberOfRecords'] + " record (s)," + responses[0]['PercentageFree'] + "% gratuito");
                x += TableEntry("Sovrascrivi politica", ((responses[0]['OverwritePolicy'] == 2) ? "Si avvolge quando è pieno" : "Non sovrascrive mai"));
                x += TableEnd();
                QH('id_TableAuditLog1', x);

                amtstack.GetAuditLog(processAuditLog1);
            }
        }

        function processAuditLog1(stack, messages) {
            auditLog = messages;
            var i, x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            // ###BEGIN###{!FileSaver}
            x += TableEnd('<div style=float:right><input id=auditFilter placeholder="' + "Filtro" + '" style=margin:4px onkeyup=auditFilter()>&nbsp;</div><div> ' + AddRefreshButton('PullAuditLog(1)') + AddButton("Pulisci il registro", 'ClearAuditLog()') /* + AddButton("Settings...", 'ShowAuditLogSettings()')*/) + '<br>';
            // ###END###{!FileSaver}
            // ###BEGIN###{FileSaver}
            x += TableEnd('<div style=float:right><input id=auditFilter placeholder="' + "Filtro" + '" style=margin:4px onkeyup=auditFilter()>&nbsp;</div><div> ' + AddRefreshButton('PullAuditLog(1)') + AddButton("Salva...", 'SaveAuditLog()') + AddButton("Pulisci il registro", 'ClearAuditLog()') /* + AddButton("Settings...", 'ShowAuditLogSettings()')*/) + '<br>';
            // ###END###{FileSaver}
            if (messages.length == 0) {
                x = "Nessun evento del registro di controllo trovato.";
            } else {
                var y = 0;
                x += '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=80px><p><td><td><td>';
                x += '<tr><td class=r1 style=width:110px>&nbsp;&nbsp;<b>' + "Tempo" + '</b><td class=r1 style=width:260px><b>' + "Iniziatore" + '</b><td class=r1><b>Action</b>';
                for (i in messages) {
                    var m = messages[i], description = m['AuditApp'], initiator = m['Initiator'];
                    y++;
                    var addr = '';
                    if (m['NetAddress'].length > 0) addr = m['NetAddress'].replace('0000:0000:0000:0000:0000:0000:0000:0001','::1');
                    if (m['Event']) description += "," + m['Event'];
                    if (m['ExStr'] != null) description += "," + m['ExStr'];
                    if (initiator != '' && addr != '') initiator += ",";
                    x += '<tr id=xamtaudit' + i + ' class=r3 onclick=showAuditDetails(' + i + ')><td class=r1 title="' + m['Time'].toLocaleString() + '">&nbsp;&nbsp;' + m['Time'].toLocaleDateString('en', { year: 'numeric', month: '2-digit', day: 'numeric' }) + '<br>&nbsp;&nbsp;' + m['Time'].toLocaleTimeString('en', { hour:'2-digit', minute:'2-digit', second:'2-digit' }) + '<td class=r1>' + initiator + addr + '<td class=r1>' + description;
                }
                x += TableEnd(y == 0 ? '&nbsp;' : '') + '<br>';
            }
            QH('id_TableAuditLog2', x);
        }

        function auditFilter() {
            var filter = Q('auditFilter').value.toLowerCase();
            for (var w in auditLog) { QV('xamtaudit' + w, filter == '' || JSON.stringify(auditLog[w]).toLowerCase().indexOf(filter) >= 0); }
        }

        // ###BEGIN###{FileSaver}
        function SaveAuditLog() {
            if (xxdialogMode || auditLog == null) return;
            SaveJsonFile('IntelAmtAuditlog', 'auditevents', "Log di controllo Intel AMT", auditLog);
        }
        // ###END###{FileSaver}

        function ClearAuditLog(x) { QH('id_dialogMessage', "Cancella registro di controllo?"); setDialogMode(1, "Registro di audizione", 3, ClearAuditLogEx); }
        function ClearAuditLogEx() {
            //amtstack.AMT_AuditLog_ClearLog(function () { PullAuditLog(); })
            var handle = amtstack.AMT_AuditLog_SetAuditLock(1,0, handle, function() { amtstack.AMT_AuditLog_ClearLog(function () { amtstack.AMT_AuditLog_SetAuditLock(0, 2, handle, function () { setTimeout(PullAuditLog,1000);}); }); });         
        }

        function ShowAuditLogSettings() {
            if (xxdialogMode) return;
            amtstack.AMT_AuditLog_RequestStateChange(2, 0, AuditLogSettingsCompleted); // Enable
        }

        function AuditLogSettingsCompleted(stack, name, responses, status) {
            if (status == 200) PullAuditLog(); else messagebox("Registro di audizione", "Errore: " + status);
        }

        function showAuditDetails(h) {
            if (xxdialogMode) return;
            var i, m = auditLog[h], x = '<div style=text-align:left>';
            x += addHtmlValue("Tempo", m['Time'].toLocaleString());
            if (m['Initiator'] != '') x += addHtmlValue("Iniziatore", m['Initiator']);
            if (m['NetAddress'] != '') x += addHtmlValue("Indirizzo", m['NetAddress']);
            x += addHtmlValue("Applicazione", m['AuditApp']);
            x += addHtmlValue("Evento", m['Event']);
            if (m['ExStr'] != null) {
                x += addHtmlValue("Dati estesi", m['ExStr']);
            } else if (m['Ex'].length > 0) {
                var e = '';
                for (i in m['Ex']) { if (e.length > 0) e += ','; e += m['Ex'].charCodeAt(i); }
                if (e != '') x += addHtmlValue("Valori dei dati", e);
                if (m['Ex'].length > 2 && ReadShort(m['Ex'], 0) == (m['Ex'].length - 2)) x += addHtmlValue("Stringa di dati", m['Ex'].substring(2));
            }
            x += '</div>';
            messagebox("Audit Event #" + (h + 1) + " Dettagli", x);
        }

// ###END###{AuditLog}

// ###BEGIN###{Certificates}

        //
        // Certificates
        //

        var xxCertificates = null;
        var xxCertPrivateKeys = null;
        var xxTlsSettings = null;
        var xxTlsCurrentCert = null;
        var xxTLSCredentialContext = null;
        var xxCaPrivateKey = null;
        var xxCaSubjectAttributes = null;

        function PullCertificates() {
            // We only deal with certificates starting with Intel AMT 6 and beyond
            amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', 'AMT_PublicPrivateKeyPair', 'AMT_TLSSettingData', 'AMT_TLSCredentialContext'], processCerts1);
        }

        function processCerts1(stack, name, responses, status) {
            if ((status == 400) || errcheck(status, stack)) return;
            QV('go16', true); // Security Settings
            xxCertificates = responses['AMT_PublicKeyCertificate'].responses;
            xxCertPrivateKeys = responses['AMT_PublicPrivateKeyPair'].responses;
            xxTlsSettings = responses['AMT_TLSSettingData'].responses;
            xxTLSCredentialContext = responses['AMT_TLSCredentialContext'].responses;

            // Select the current TLS certificate in the drop down box
            xxTlsCurrentCert = null;
            if (xxTLSCredentialContext.length > 0) {
                var certInstanceId = xxTLSCredentialContext[0]['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                for (var i in xxCertificates) { if (xxCertificates[i]['InstanceID'] == certInstanceId) { xxTlsCurrentCert = i; } }
            }

            // ###BEGIN###{Mode-NodeWebkit}
            try { if ((currentcomputer['tls'] == 0) && (xxTlsSettings[0]['MutualAuthentication'] !== true)) { QV('tlsNotification4', true); } } catch (ex) { console.log(ex); }
            // ###END###{Mode-NodeWebkit}

            // Setup the certificates
            for (var i in xxCertificates) {
                xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true);
                xxCertificates[i].X509Certificate = window.atob(xxCertificates[i]['X509Certificate']);
                xxCertificates[i].XIssuer = parseCertName(xxCertificates[i]['Issuer']);
                xxCertificates[i].XSubject = parseCertName(xxCertificates[i]['Subject']);
            }
            amtcert_linkCertPrivateKey(xxCertificates, xxCertPrivateKeys); // This links all certificates and private keys

            updateCertificates();
        }

        function parseCertName(x) {
            var j, r = {}, xx = x.split(',');
            for (var i in xx) { j = xx[i].indexOf('='); r[xx[i].substring(0, j)] = xx[i].substring(j + 1); }
            return r;
        }

        function getTlsSecurityState(x) {
            if (xxTlsSettings[x]['Enabled'] == false) return "Disabilitato";
            var r = ((xxTlsSettings[x]['MutualAuthentication'] == true) ? "TLS di mutua autorizzazione" : "TLS di autenticazione server") + ((xxTlsSettings[x]['AcceptNonSecureConnections'] == true) ? " e non TLS" : '');
            if ((xxTlsSettings[x]['MutualAuthentication'] == true) && (xxTlsSettings[x]['TrustedCN'])) {
                var trustedCn = MakeToArray(xxTlsSettings[x]['TrustedCN']);
                if (trustedCn.length > 0) { r += ', ' + ((trustedCn.length > 1) ? 'Trusted names' : 'Trusted name') + ': ' + trustedCn.join(', ') + '.'; }
            }
            return r;
        }

        function updateCertificates() {
            if (xxCertificates == null) return;

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // General settings
            var x = TableStart();
            x += TableEntry("Sicurezza TLS remota", addLinkConditional(getTlsSecurityState(remoteNdx), 'showSetTlsSecurityDlg()', xxAccountAdminName));
            x += TableEntry("Sicurezza TLS locale", addLinkConditional(getTlsSecurityState(localNdx), 'showSetTlsSecurityDlg()', xxAccountAdminName));
            x += TableEnd();
            x += '<br>' + TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gestisci i certificati Intel&reg; AMT per questo computer." + '<br><br>';
            if (xxCertificates.length == 0 && xxCertPrivateKeys.length == 0) {
                x += '<div style=padding-left:15px><br><i>' + "Nessun certificato trovato." + '</i></div><br>';
            } else {
                for (var i in xxCertificates) {
                    var desc = '';
                    if (xxCertificates[i].TrustedRootCertficate) desc = ", Radice attendibile";
                    if (xxCertificates[i].XPrivateKey) desc = ", Chiave privata";
                    if (i == xxTlsCurrentCert) desc += ", Certificato TLS";
                    x += '<div class=itemBar onclick=showCertDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</b><i>' + desc + '</i></div></div>';
                }
                for (var i in xxCertPrivateKeys) {
                    if (!xxCertPrivateKeys[i].XCert) {
                        x += '<div class=itemBar onclick=showKeyPairDetails(' + i + ')><div style=padding-top:3px><i>' + "Coppia di chiavi private non assegnate #" + i + '</i></div></div>';
                    }
                }
            }
            var buttons = AddRefreshButton('PullCertificates()');
            if (xxAccountAdminName) { buttons += (AddButton("Aggiungi certificato ...", 'addCertButton()') + AddButton("Rilascia certificato ...", 'issueCertButton()')); }
            x += '<br><td class=r1>' + TableEnd(buttons);
            QH('id_TableCerts', x);
        }

        function showKeyPairDetails(h) {
            var x = "Questa è una coppia di chiavi di certificato pubblico / privato che non appartiene ad alcun certificato. Questa voce dovrebbe essere temporanea.";
            setDialogMode(11, "Key Pair #" + h, 5, function (b) { if (b == 2) { amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertPrivateKeys[h]['InstanceID'] }, PullCertificates, 0, 1); } }, x);
        }

        var xxCertSubjectNames = { 'CN': "Nome comune", 'O': "Organizzazione", 'OU': "Unità organizzativa", 'S': "Stato / Provincia", 'ST': "Stato / Provincia", 'L': "Località", 'C': "Nazione", 'SN': "Cognome", 'GN': "Nome di battesimo" };
        function showCertDetails(h) {
            if (xxdialogMode) return;
            var c = xxCertificates[h], x = '<br>';
            // ###BEGIN###{FileSaver}
            x += addHtmlValue("Certificato", c.X509Certificate.length + " byte," + '<a style=cursor:pointer;color:blue onclick=downloadCert(' + h + ')>' + "Scarica" + '</a>');
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            x += addHtmlValue("Certificato", c.X509Certificate.length + " byte");
            // ###END###{!FileSaver}
            x += addHtmlValue("Radice attendibile", c.TrustedRootCertficate ? "sì" : "No");
            if (c.TrustedRootCertficate == false && c.XPrivateKey) { x += addHtmlValue("Chiave privata", "Presente"); }

            // Show certificate usages
            /*
            y = [];
            if (extKeyUsage != null) {
                if (extKeyUsage.clientAuth == true) { y.push("TLS&nbsp;Client"); }
                if (extKeyUsage.codeSigning == true) { y.push("Code&nbsp;Signing"); }
                if (extKeyUsage.emailProtection == true) { y.push("EMail"); }
                if (extKeyUsage.serverAuth == true) { y.push("TLS&nbsp;Server"); }
                if (extKeyUsage["2.16.840.1.113741.1.2.1"] == true) { y.push("Intel&reg;&nbsp;AMT Console"); }
                if (extKeyUsage["2.16.840.1.113741.1.2.2"] == true) { y.push("Intel&reg;&nbsp;AMT Agent"); }
                if (extKeyUsage["2.16.840.1.113741.1.2.3"] == true) { y.push("Intel&reg;&nbsp;AMT Activation"); }
                if (extKeyUsage.timeStamping == true) { y.push("Time&nbsp;Stamping"); }
                if (y.length > 0) { x += addHtmlValueNoTitle("Certificate Usage", y.join(', ') + '.') + '<br clear=all />'; }
            }
            */

            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Oggetto del certificato" + '</i></div><br>';
            for (var i in c.XSubject) { if (c.XSubject[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(c.XSubject[i])); } }
            // x += addHtmlValueNoTitle("Fingerprint", c.fingerprint.substring(0,29) + '<br />' + c.fingerprint.substring(30)); // TODO: Parse the certificate using Forge and get the fingerprint
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificato dell'Emittente" + '</i></div><br>';
            for (var i in c.XIssuer) { if (c.XIssuer[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(c.XIssuer[i])); } }
            setDialogMode(11, "Certificato -" + EscapeHtml(c.XSubject['CN']), 5, function (b) {
                if (b == 2) {
                    // If there is a private key, delete it.
                    if (xxCertificates[h].XPrivateKey) amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertificates[h].XPrivateKey['InstanceID'] }, function () { }, 0, 1);
                    // Delete the certificate
                    amtstack.Delete('AMT_PublicKeyCertificate', xxCertificates[h], certificateRemoved, 0, 1);
                }
            }, x);
        }

        // ###BEGIN###{FileSaver}
        function downloadCert(h) { 
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(xxCertificates[h].X509Certificate), xxCertificates[h].XSubject['CN'] + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', xxCertificates[h].XSubject['CN'] + '.cer');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, xxCertificates[h].X509Certificate, 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        function cert_FileSelectHandler(e) {
            haltEvent(e);
            if (e.dataTransfer.files.length == 1) {
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.p12')) {
                    issueCertButton(e.dataTransfer.files);
                } else {
                    addCertButton(e.dataTransfer.files);
                }
            }
        }

        var xxDragDropCertFiles = null;
        function addCertButton(files) {
            if (xxdialogMode || !xxAccountAdminName) return;
            var x = '<div style=height:10px></div>', op0 = '', op2 = '';
            xxDragDropCertFiles = files;
            // ###BEGIN###{CertificateManager}
            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if (amtversion > 12) { op2 = '<option value=2>' + "MeshCommander Web Server Root" + '</option>'; }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}
            if (certificateStore.length > 0) { op0 += '<option value=0>' + "Aggiungi dal gestore certificati" + '</option>'; }
            if ((!xxDragDropCertFiles) && ((op0 != '') || (op2 != ''))) { x += '<div style=height:26px;margin-top:4px><select onchange=addCertButtonUpdate() id=certoptype style=float:right;width:260px>' + op0 + '<option value=1>' + "Aggiungi dal file del certificato" + '</option>' + op2 + '</select><div style=padding-top:4px>' + "operazione" + '</div></div>'; }
            x += '<div id=dxcertfileop1>';
            var input = '<input id=certopen onchange=addCertButtonUpdate() type=file style=float:right;width:260px accept=".crt,.cer,.pem">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:260px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div style=height:26px;margin-top:4px>' + input + '<div style=padding-top:4px>' + "File del certificato" + '</div></div></div>';
            if (certificateStore.length > 0) {
                x += '<div id=dxcertfileop2><div style=height:26px;margin-top:4px><select id=certhandle style=float:right;width:260px>';
                for (var i in certificateStore) {
                    var certificate = certificateStore[i], name = certificate.cert.subject.getField('CN').value;
                    x += '<option value=' + certificate['h'] + '>' + name + '</option>';
                }
                x += '</select><div style=padding-top:4px>' + "Certificato" + '</div></div></div>';
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{!CertificateManager}
            var input = '<input id=certopen onchange=addCertButtonUpdate() type=file style=float:right;width:260px accept=".cer,.pem">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:260px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div style=height:26px;margin-top:4px>' + input + '<div style=padding-top:4px>' + "File del certificato" + '</div></div>';
            // ###END###{!CertificateManager}
            x += '<div style=height:26px;margin-top:4px><select id=certtype style=float:right;width:260px><option value=1>' + "Certificato radice attendibile" + '</option><option value=0>' + "Certificato a catena" + '</option></select><div style=padding-top:4px>' + "Tipo di certificato" + '</div></div>';
            setDialogMode(11, "Aggiungi certificato", 3, addCertButtonOk, x);
            addCertButtonUpdate();
        }

        function addCertButtonUpdate() {
            // ###BEGIN###{CertificateManager}
            if ((!xxDragDropCertFiles) && (certificateStore.length > 0)) {
                QV('dxcertfileop2', Q('certoptype').value == 0);
                QV('dxcertfileop1', Q('certoptype').value == 1);
                if (Q('certoptype').value == 0) { QE('idx_dlgOkButton', true); return; }
            }
            // ###END###{CertificateManager}
            var certopen = getInputElement('certopen');
            QE('idx_dlgOkButton', !certopen || (certopen.files.length == 1) || (Q('certoptype').value == 2));
        }

        function addCertButtonOk() {
            // ###BEGIN###{CertificateManager}
            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if (Q('certoptype').value == 2) {
                var certbin = null;
                if (webserver == null) {
                    webserver = CreateWebServer();
                    webserver.generateCertificate(0);
                    certbin = webserver.rootCert;
                    webserver = null;
                } else {
                    certbin = webserver.rootCert;
                }

                // This is a .PEM file, keep everything between BEGIN/END, clean it up and use as-is. It's already Base64.
                var i = certbin.indexOf('-----BEGIN CERTIFICATE-----');
                if (i >= 0) {
                    certbin = certbin.substring(i + 27);
                    i = certbin.indexOf('-----END CERTIFICATE-----');
                    if (i >= 0) certbin = certbin.substring(0, i)
                    certbin = certbin.replace(/\r\n/g, '');
                    if (getSelectElement('certtype').value == 1) {
                        amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(certbin, certificateAdded);
                    } else {
                        amtstack.AMT_PublicKeyManagementService_AddCertificate(certbin, certificateAdded);
                    }
                }
                return;
            }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}
            if ((xxDragDropCertFiles) || (certificateStore.length == 0) || (Q('certoptype').value == 1)) {
                var certopen = getInputElement('certopen');
                var files = xxDragDropCertFiles;
                if (certopen) files = certopen.files;
                if (files && files.length == 1) {
                    var reader = new FileReader();
                    reader.onload = addCertButtonOk2;
                    reader.readAsBinaryString(files[0]);
                }
            } else {
                var certificate = getCertificate(Q('certhandle').value)
                if (getSelectElement('certtype').value == 1) {
                    amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(certificate['certbin'], certificateAdded);
                } else {
                    amtstack.AMT_PublicKeyManagementService_AddCertificate(certificate['certbin'], certificateAdded);
                }
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{!CertificateManager}
            var certopen = getInputElement('certopen');
            var files = xxDragDropCertFiles;
            if (certopen) files = certopen.files;
            if (files && files.length == 1) {
                var reader = new FileReader();
                reader.onload = addCertButtonOk2;
                reader.readAsBinaryString(files[0]);
            }
            // ###END###{!CertificateManager}
        }
        
        function addCertButtonOk2(file) {
            var data = file.target.result;
            var i = data.indexOf('-----BEGIN CERTIFICATE-----');
            if (i >= 0) {
                // This is a .PEM file, keep everything between BEGIN/END, clean it up and use as-is. It's already Base64.
                data = data.substring(i + 27);
                i = data.indexOf('-----END CERTIFICATE-----');
                if (i >= 0) data = data.substring(0, i)
                data = data.replace(/\r\n/g, '');
            } else {
                // This is a .CER file, just base64 encode it and we should be ok.
                data = btoa(data);
            }
            if (getSelectElement('certtype').value == 1) {
                amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(data, certificateAdded);
            } else {
                amtstack.AMT_PublicKeyManagementService_AddCertificate(data, certificateAdded);
            }
        }

        function issueCertButton(files) {
            if (xxdialogMode || !xxAccountAdminName) return;
            xxDragDropCertFiles = files;

            // ###BEGIN###{CertificateManager}
            var x = '', certCount = getCertificateWithKeyCount();
            if ((!xxDragDropCertFiles) && (certCount > 0)) { x += '<div style=height:26px;margin-top:4px><select onchange=addCertButtonUpdate() id=certoptype style=float:right;width:230px><option value=0>' + "Rilascio dal gestore certificati" + '</option><option value=1>' + "Emissione dal file del certificato" + '</option></select><div style=padding-top:4px>Operation</div></div>'; }
            x += '<div id=dxcertfileop1>', input = '<input id=certopen onchange=issueCertButtonUpdate() type=file style=float:right;width:230px accept=".p12">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:230px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div style=height:26px;margin-top:4px>' + input + '<div style=padding-top:4px>' + "File del certificato" + '</div></div><div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certopenpass type=password autocomplete=off style=float:right;width:230px><div style=padding-top:4px>' + "Password del certificato" + '</div></div></div>';
            if (certificateStore.length > 0) {
                x += '<div id=dxcertfileop2><div style=height:26px;margin-top:4px><select id=certhandle style=float:right;width:230px>';
                for (var i in certificateStore) {
                    var certificate = certificateStore[i], name = certificate.cert.subject.getField('CN').value
                    if (certificate['privateKey']) { x += '<option value=' + certificate['h'] + '>' + name + '</option>'; }
                }
                x += '</select><div style=padding-top:4px>' + "Certificato" + '</div></div></div>';
            }
            // ###END###{CertificateManager}

            // ###BEGIN###{!CertificateManager}
            var x = '', input = '<input id=certopen type=file style=float:right;width:230px onchange=issueCertButtonUpdate() accept=".p12">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:230px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div styleheight:26px;margin-top:14px>' + input + '<div style=padding-top:4px>Certificate file</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certopenpass type=password autocomplete=off style=float:right;width:230px><div style=padding-top:4px>' + "Password del certificato" + '</div></div>';
            // ###END###{!CertificateManager}

            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificato Intel&reg; AMT" + '</i></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certcn style=float:right;width:230px><div style=padding-top:4px>' + "Nome comune" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certo style=float:right;width:230px><div style=padding-top:4px>' + "Organizzazione" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certst style=float:right;width:230px><div style=padding-top:4px>' + "Stato / Provincia" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certc style=float:right;width:230px><div style=padding-top:4px>' + "Nazione" + '</div></div>';
            x += '<div>' + "Usi del certificato" + '</div><ul style="list-style-type:none;height:100px;overflow:auto;width:100%;border: 1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0">';
            //x += '<li><label><input type=checkbox id=d11_cu1>' + "Intel&reg; AMT Console" + '</label></li>';
            //x += '<li><label><input type=checkbox id=d11_cu2>' + "Intel&reg; AMT Agent" + '</label></li>';
            //x += '<li><label><input type=checkbox id=d11_cu3>' + "Intel&reg; AMT Activation" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu4 checked>' + "Server TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu5>' + "Client TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu6>' + "Protezione e-mail" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu7>' + "Firma del codice" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu8>' + "Timestamp" + '</label></li>';
            x += '</ul>';
            setDialogMode(11, "Rilascio certificato", 3, issueCertButtonOk, x);
            issueCertButtonUpdate();
        }

        function issueCertButtonUpdate() {
            // ###BEGIN###{CertificateManager}
            var certCount = getCertificateWithKeyCount();
            if ((!xxDragDropCertFiles) && (certCount > 0)) {
                QV('dxcertfileop2', Q('certoptype').value == 0);
                QV('dxcertfileop1', Q('certoptype').value == 1);
                QE('idx_dlgOkButton', (getInputElement('certcn').value != '') && (getInputElement('certo').value != '') && (getInputElement('certst').value != '') && (getInputElement('certc').value != ''));
                return;
            }
            // ###END###{CertificateManager}
            var certopen = getInputElement('certopen');
            QE('certopenpass', !certopen || (certopen && certopen.files.length == 1));
            var x = (!certopen || certopen.files.length < 2);
            if ((!certopen || (certopen && certopen.files.length)) == 1 && Q('certopenpass').value == '') x = false;
            if (getInputElement('certcn').value == '' || getInputElement('certo').value == '' || getInputElement('certst').value == '' || getInputElement('certc').value == '') { x = false; }
            QE('idx_dlgOkButton', x);
        }

        function issueCertButtonOk() {
            // ###BEGIN###{CertificateManager}
            if ((xxDragDropCertFiles) || (certificateStore.length == 0) || (Q('certoptype').value == 1)) {
                var certopen = getInputElement('certopen');
                var files = xxDragDropCertFiles;
                if (certopen) files = certopen.files;
                if (files && files.length == 1) {
                    // Issue a certificate using this file
                    var reader = new FileReader();
                    reader.onload = issueCertButtonOk2;
                    reader.readAsBinaryString(files[0]);
                } else {
                    // Issue a certificate using a dummy CA
                    issueCertButtonOk3(null);
                }
            } else {
                // Save the certificate store certificate as a p12 and load it back up using the regular user flow. This makes the code smaller but slower.
                var certificate = getCertificate(Q('certhandle').value);
                var certBase64 = forge.util.encode64(forge.asn1.toDer(forge.pkcs12.toPkcs12Asn1(certificate['privateKey'], certificate['cert'], 'pass')).getBytes());
                amtcert_loadP12File(atob(certBase64), 'pass', issueCertButtonOk3);
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{!CertificateManager}
            var certopen = getInputElement('certopen');
            var files = xxDragDropCertFiles;
            if (certopen) files = certopen.files;
            if (files && files.length == 1) {
                // Issue a certificate using this file
                var reader = new FileReader();
                reader.onload = issueCertButtonOk2;
                reader.readAsBinaryString(files[0]);
            } else {
                // Issue a certificate using a dummy CA
                issueCertButtonOk3(null);
            }
            // ###END###{!CertificateManager}
        }

        function issueCertButtonOk2(file) {
            // Load the CA certificate and private key
            var r = amtcert_loadP12File(file.target.result, Q('certopenpass').value, issueCertButtonOk3);
            if (r == false) { messagebox("Rilascio certificato", "Impossibile decrittografare / decodificare il certificato."); return; }
        }

        function issueCertButtonOk3(privateKey, subjectAttributes, cert) {
            // Ask Intel AMT to generate a key pair
            xxCaPrivateKey = privateKey;
            xxCaSubjectAttributes = subjectAttributes;
            amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, GenerateKeyPairResponse);
        }

        function GenerateKeyPairResponse(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi. Stato: " + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi," + response.Body['ReturnValueStr']); return; }

            // Get the new key pair
            amtstack.Enum('AMT_PublicPrivateKeyPair', GenerateKeyPairResponse2, response.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']);
        }

        function GenerateKeyPairResponse2(stack, serviceName, response, status, tag) {
            if (status != 200) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi. Stato: " + status); return; }
            var DERKey = null;
            for (var i in response) { if (response[i]['InstanceID'] == tag) DERKey = response[i]['DERKey']; }

            // Get certificate values
            var certattributes = { 'CN': getInputElement('certcn').value, 'O': getInputElement('certo').value, 'ST': getInputElement('certst').value, 'C': getInputElement('certc').value };
            var issuerattributes = { 'CN': "Certificato radice non attendibile" };
            if (xxCaPrivateKey != null && xxCaSubjectAttributes) {
                issuerattributes = {};
                for (var i in xxCaSubjectAttributes) {
                    issuerattributes[xxCaSubjectAttributes[i].shortName] = xxCaSubjectAttributes[i].value; // The issuing CA's subject attributes 
                }
            } 

            // Figure out the extended key usages
            var extKeyUsage = { name: 'extKeyUsage' }
            //if (Q('d11_cu1').checked) { extKeyUsage['2.16.840.1.113741.1.2.1'] = true; extKeyUsage.clientAuth = true; }
            //if (Q('d11_cu2').checked) { extKeyUsage['2.16.840.1.113741.1.2.2'] = true; extKeyUsage.clientAuth = true; }
            //if (Q('d11_cu3').checked) { extKeyUsage['2.16.840.1.113741.1.2.3'] = true; extKeyUsage.clientAuth = true; }
            if (Q('d11_cu4').checked) { extKeyUsage.serverAuth = true; }
            if (Q('d11_cu5').checked) { extKeyUsage.clientAuth = true; }
            if (Q('d11_cu6').checked) { extKeyUsage.emailProtection = true; }
            if (Q('d11_cu7').checked) { extKeyUsage.codeSigning = true; }
            if (Q('d11_cu8').checked) { extKeyUsage.timeStamping = true; }

            // Sign the key pair using the CA certifiate
            var cert = amtcert_signWithCaKey(DERKey, xxCaPrivateKey, certattributes, issuerattributes, extKeyUsage);
            if (cert == null) { messagebox("Rilascio certificato", "Impossibile firmare il certificato."); return; }

            // Place the resulting signed certificate back into AMT
            var pem = forge.pki.certificateToPem(cert).replace(/(\r\n|\n|\r)/gm, '');
            amtstack.AMT_PublicKeyManagementService_AddCertificate(pem.substring(27, pem.length - 25), GenerateKeyPairResponse4);
        }

        function GenerateKeyPairResponse4(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Rilascio certificato", "Impossibile generare la coppia di chiavi. Stato: " + status); return; }
            PullCertificates();
        }

        function certificateAdded(stack, serviceName, response, status) { if (status != 200 || response.Body['ReturnValue'] != 0) { messagebox("Aggiungi certificato", "Impossibile aggiungere il certificato, errore" + (status != 200 ? status : response.Body['ReturnValueStr'])); } else PullCertificates(); }
        function certificateRemoved(stack, serviceName, header, status) { if (status != 200) { messagebox("Rimuovi certificato", "Impossibile rimuovere il certificato, errore" + status); } else PullCertificates(); }

        function getInputElement(id) { var allelements = document.getElementsByTagName('input'); for (t = 0; t < allelements.length; t++) { if (allelements[t].id == id) return allelements[t]; } }
        function getSelectElement(id) { var allelements = document.getElementsByTagName('select'); for (t = 0; t < allelements.length; t++) { if (allelements[t].id == id) return allelements[t]; } }

        function showSetTlsSecurityDlg(x) {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><select onchange=showSetTlsSecurityDlgUpdate() id=tlscert style=float:right;width:260px><option value=-1>' + "Nessun certificato, TLS disabilitato" + '</option>';
            for (var i in xxCertificates) { if (xxCertificates[i].TrustedRootCertficate == false && xxCertificates[i].XPrivateKey) { x += '<option value=' + i + '>' + xxCertificates[i].XSubject['CN'] + '</option>'; } }
            x += '</select><div style=padding-top:4px>' + "Certificato" + '</div></div>';

            x += '<div style=height:26px;margin-top:4px><select id=tlsremote style=float:right;width:260px onchange=showSetTlsSecurityDlgUpdate()><option value=0>Server-auth TLS only</option><option value=1>Server-auth, non-TLS allowed</option>';
            x += '<option value=2>Mutual-auth TLS only</option><option value=3>Mutual-auth, non-TLS allowed</option>'; // Support for mutual-auth TLS seems to have been removed on AMT8 and after ??
            x += '</select><div style=padding-top:4px>Security</div></div><div style=height:26px id=d11rcn title="' + "Elenco separato da virgole di nomi comuni di certificati che potranno connettersi in remoto." + '"><input id=d11_rcn style=float:right;width:260px onkeyup=showSetTlsSecurityDlgUpdate() placeholder="' + "nome1, nome2" + '"><div style=padding-top:4px>' + "CN remoti" + '</div></div>';

            setDialogMode(11, "Impostazioni TLS", 3, showSetTlsSecurityDlgOk, x);

            // Select the current TLS certificate in the drop down box
            if ((xxTLSCredentialContext.length == 0) || (xxTlsSettings[0]['Enabled'] == false) || (xxTlsSettings[1]['Enabled'] == false)) {
                getSelectElement('tlscert').value = -1;
            } else {
                var certInstanceId = xxTLSCredentialContext[0]['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                for (var i in xxCertificates) { if (xxCertificates[i]['InstanceID'] == certInstanceId) { getSelectElement('tlscert').value = i; } }
            }

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // Select correct TLS options in the drop down boxes
            getSelectElement('tlsremote').value = ((xxTlsSettings[remoteNdx]['MutualAuthentication'] == true) ? 2 : 0) + ((xxTlsSettings[remoteNdx]['AcceptNonSecureConnections'] == true) ? 1 : 0);
            if (xxTlsSettings[remoteNdx]['TrustedCN']) { Q('d11_rcn').value = MakeToArray(xxTlsSettings[remoteNdx]['TrustedCN']).join(', '); }

            showSetTlsSecurityDlgUpdate();
        }

        function showSetTlsSecurityDlgUpdate() {
            var h = getSelectElement('tlscert').value;
            QE('tlsremote', h != -1);
            QV('d11rcn', (h != -1) && (getSelectElement('tlsremote').value > 1));
            var ok = true;
            if ((getSelectElement('tlsremote').value > 1) && (!splitDomains(Q('d11_rcn').value))) { ok = false; }
            QE('idx_dlgOkButton', ok);
        }

        var setTlsSecurityPendingCalls;
        var setTlsSecurityDeleteCredentialContext;
        function showSetTlsSecurityDlgOk() {
            var h = getSelectElement('tlscert').value;
            var r = getSelectElement('tlsremote').value;
            var xxTlsSettings2 = Clone(xxTlsSettings);
            setTlsSecurityPendingCalls = 0;
            setTlsSecurityDeleteCredentialContext = null;

            if (h != -1) {
                // Set the TLS certificate
                if (xxTLSCredentialContext.length > 0) {
                    // Modify the current context
                    var newTLSCredentialContext = Clone(xxTLSCredentialContext[0]);
                    newTLSCredentialContext['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'] = xxCertificates[h]['InstanceID'];
                    amtstack.Put('AMT_TLSCredentialContext', newTLSCredentialContext, setTlsSecurityResponse, 0, 1);
                    setTlsSecurityPendingCalls++;
                } else {
                    // Add a new security context
                    amtstack.Create('AMT_TLSCredentialContext', {
                        'ElementInContext':'<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + xxCertificates[h]['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters>',
                        'ElementProvidingContext':'<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_TLSProtocolEndpointCollection') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="ElementName">TLSProtocolEndpointInstances Collection</w:Selector></w:SelectorSet></a:ReferenceParameters>' }, setTlsSecurityResponse);
                    setTlsSecurityPendingCalls++;
                }
            } else {
                // Clear the TLS certificate association (MOVE THIS)
                if (xxTLSCredentialContext.length > 0) { setTlsSecurityDeleteCredentialContext = Clone(xxTLSCredentialContext[0]); }
            }

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // Remote TLS settings
            xxTlsSettings2[remoteNdx]['Enabled'] = (h != -1);
            xxTlsSettings2[remoteNdx]['MutualAuthentication'] = (r >= 2);
            xxTlsSettings2[remoteNdx]['AcceptNonSecureConnections'] = ((r % 2) == 1);
            xxTlsSettings2[remoteNdx]['TrustedCN'] = splitDomains(Q('d11_rcn').value);
            
            // Local TLS settings
            xxTlsSettings2[localNdx]['Enabled'] = (h != -1);
            xxTlsSettings2[localNdx]['TrustedCN'] = splitDomains(Q('d11_rcn').value); // This is required for old Intel AMT (v7 for sure) because older AMT support local interface mutual-auth and don't well if you don't set this.

            // Mutual-auth TLS requires time sync
            if (r >= 2) {
                setTlsSecurityPendingCalls++;
                amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(function (stack, name, response, status) {
                    if (status != 200) { messagebox('', "Impossibile impostare l'ora, status =" + status); return; }
                    if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossibile impostare l'ora, errore: " + response.Body['ReturnValueStr']); return; }
                    //var now = new Date(), Tm1 = Math.round((now.getTime() - (now.getTimezoneOffset() * 60000)) / 1000);
                    var now = new Date(), Tm1 = Math.round(now.getTime() / 1000);
                    amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, function () { setTlsSecurityResponse(); });
                });
            }

            // Update TLS settings
            setTlsSecurityPendingCalls += 2;
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[0], setTlsSecurityResponse, 0, 1, xxTlsSettings2[0]);
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[1], setTlsSecurityResponse, 0, 1, xxTlsSettings2[1]);

            statusbox("Impostazioni TLS", "Applicazione di nuove impostazioni di sicurezza ...");
        }

        // Split a string into a array of domains. Return null if not a valid list.
        function splitDomains(str) {
            str = str.split(',');
            if (str.length == 0) return;
            for (var i in str) { str[i] = str[i].trim(); if ((str[i].indexOf(' ') >= 0) || (str[i].length == 0)) return; }
            if (str.length > 4) return;
            return str;
        }

        function setTlsSecurityResponse(stack, name, response, status) {
            if (stack) {
                if (status != 200) { messagebox('', "Impossibile impostare la sicurezza TLS, status =" + status); return; }
                if (response.Body['ReturnValueStr'] && !methodcheck(response)) return;
            }

            // Check if all the calls are done & perform a commit
            if ((--setTlsSecurityPendingCalls) == 0) { amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, setTlsSecurityResponse2); }
        }

        function setTlsSecurityResponse2(stack, name, response, status) {
            if (status != 200) { messagebox('', "Impossibile impostare la sicurezza TLS, status =" + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossibile impostare la sicurezza TLS, errore: " + response.Body['ReturnValueStr']); return; }
            setTimeout(setTlsSecurityResponse3, 2000);
        }

        function setTlsSecurityResponse3() {
            if (setTlsSecurityDeleteCredentialContext != null) { amtstack.Delete('AMT_TLSCredentialContext', setTlsSecurityDeleteCredentialContext, function () { }); }
            PullCertificates();
            setDialogMode();
            amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(processSystemTime);
        }

// ###END###{Certificates}

// ###BEGIN###{AgentPresence}

        //
        // AGENT PRESENCE
        //

        var xxWatchdog = null;

        function PullWatchdog() {
            amtstack.BatchEnum(null, ['*AMT_AgentPresenceCapabilities', 'AMT_AgentPresenceWatchdog', 'AMT_AgentPresenceWatchdogAction', 'AMT_StateTransitionCondition', 'CIM_ConcreteDependency'], PullWatchdogResponse);
        }

        function PullWatchdogResponse(stack, name, responses, status) {
            if ((status == 200) && (responses['AMT_AgentPresenceCapabilities'].status == 200)) {
                xxWatchdog = responses;
            
                // Place the actions into the watchdogs for easy navigation.
                for (var i in xxWatchdog['CIM_ConcreteDependency'].responses) {
                    var link = xxWatchdog['CIM_ConcreteDependency'].responses[i];
                    var x1 = getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'CreationClassName');
                    if (x1 && x1['Value'] == 'AMT_AgentPresenceWatchdog') {
                        var deviceid = getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'DeviceID')['Value'];
                        var policyConditionName = getItem(link['Dependent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyConditionName')['Value'];
                        var watchdog = getItem(xxWatchdog['AMT_AgentPresenceWatchdog'].responses, 'DeviceID', deviceid);
                        var transitionPolicy = getItem(xxWatchdog['AMT_StateTransitionCondition'].responses, 'PolicyConditionName', policyConditionName);
                        if (!watchdog.transitions) watchdog.transitions = [];
                        watchdog.transitions.push(transitionPolicy);
                    }
                    if (x1 && x1['Value'] == 'AMT_StateTransitionCondition') {
                        var policyConditionName = getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyConditionName')['Value'];
                        var policyActionName = getItem(link['Dependent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyActionName')['Value'];
                        var transitionPolicy = getItem(xxWatchdog['AMT_StateTransitionCondition'].responses, 'PolicyConditionName', policyConditionName);
                        var watchdogAction = getItem(xxWatchdog['AMT_AgentPresenceWatchdogAction'].responses, 'PolicyActionName', policyActionName);
                        if (!transitionPolicy.actions) transitionPolicy.actions = [];
                        transitionPolicy.actions.push(watchdogAction);
                    }
                }

                updateWatchdog();
                QV('go19', true); // Show Agent Presence panel
            }
        }

        var watchdogEnabledStates = [ "Sconosciuto", "Altro", "Abilitato", "Disabilitato", "Chiudere", "Non applicabile", "Abilitato ma offline", "In prova", "differite", "quiesce", "Di partenza" ];
        var watchdogMonitoredEntity = [ "Sconosciuto", "Altro", "Sistema operativo", "Processo di avvio del sistema operativo", "Processo di spegnimento del sistema operativo", "Processo di avvio del firmware", "Processo di avvio del BIOS", "Applicazione", "Processore di servizio" ];
        function updateWatchdog() {
            if (xxWatchdog == null) return;
            var x = '';

            // Global Agent Presense Values
            x += TableStart();
            x += TableEntry("Numero massimo", xxWatchdog['AMT_AgentPresenceCapabilities'].response['MaxTotalAgents'] + " cani da guardia");
            x += TableEntry("Numero massimo di azioni totali", xxWatchdog['AMT_AgentPresenceCapabilities'].response['MaxTotalActions'] + " Azioni");
            // x += TableEntry("Maximum EAC Watchdogs", xxWatchdog['AMT_AgentPresenceCapabilities'].response['MaxEacAgents'] + " watchdogs");
            x += TableEnd() + '<br>';

            // Watchdogs
            x += TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gestisci i watchdog di presenza degli agenti Intel&reg; AMT." + '<br><br>';
            if ((xxWatchdog['AMT_AgentPresenceWatchdog'].responses == null) || (xxWatchdog['AMT_AgentPresenceWatchdog'].responses.length == 0)) {
                x += '<div style=padding-left:15px><i>' + "Nessun watchdog di presenza agente trovato." + '</i></div><br>';
            } else {
                for (var i in xxWatchdog['AMT_AgentPresenceWatchdog'].responses) {
                    var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];
                    var n = guidToStr(rstr2hex(atob(w['DeviceID'])));
                    if (w['MonitoredEntityDescription'] && w['MonitoredEntityDescription'] != '') n = EscapeHtml(w['MonitoredEntityDescription']);
                    x += '<div class=itemBar onclick=showWatchdogDetails(' + i + ')><input type=button style=float:right value="' + "Aggiungi azione ..." + '" onclick=addWatchdogAction(event,' + i + ')>';
                    if (w.transitions) { x += '<input type=button style=float:right value="' + "Elimina azioni ..." + '" onclick=deleteWatchdogActions(event,' + i + ')>'; }
                    x += '<div style=padding-top:3px><b>' + n + '</b>, ' + amtstack.WatchdogCurrentStates[w['CurrentState']] + '</div>';
                    var xx = '';
                    for (var j in w.transitions) {
                        var t = w.transitions[j];
                        if (xx != '') xx += '<br>';
                        xx += getWatchdogTransitionStr(t['OldState']) + ' &rarr; ' + getWatchdogTransitionStr(t['NewState']);
                        if (t.actions) {
                            var action = t.actions[0];
                            if (action['EventOnTransition'] == true) { xx += " : Evento da registrare"; }
                        }
                    }
                    if (xx != '') { x += '<div style=padding:12px>' + xx + '</div>'; }
                    x += '</div>';
                }
            }
            x += '<br>';
            x += TableEnd(AddRefreshButton('PullWatchdog()') + AddButton("Aggiungi watchdog ...", 'AddWatchdog()'));
            x += '<br>';

            QH('id_TableSystemAgentPresence', x);
        }

        function getWatchdogTransitionStr(s) {
            if (s == 31) return "Qualsiasi stato";
            var x = '';
            for (var i in amtstack.WatchdogCurrentStates) { if ((s & i) != 0) { x += ', ' + amtstack.WatchdogCurrentStates[i]; } }
            return x.substring(2);
        }

        function showWatchdogDetails(i) {
            var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];

            var x = '';
            //x += addHtmlValue("DeviceID", guidToStr(rstr2hex(atob(w['DeviceID']))));
            if (w['MonitoredEntityDescription'] && w['MonitoredEntityDescription'] != '') x += addHtmlValue("Descrizione", EscapeHtml(w['MonitoredEntityDescription']));
            x += addHtmlValue("Entità monitorata", watchdogMonitoredEntity[w['MonitoredEntity']]);
            x += addHtmlValue("Stato attuale", amtstack.WatchdogCurrentStates[w['CurrentState']]);
            x += addHtmlValue("Stato abilitato", watchdogEnabledStates[w['EnabledState']]);
            x += addHtmlValue("Intervallo di avvio", w['StartupInterval'] + " secondo (s)");
            x += addHtmlValue("Intervallo di timeout", w['TimeoutInterval'] + " secondo (s)");

            setDialogMode(11, format("Cane da guardia {0}", guidToStr(rstr2hex(atob(w['DeviceID'])))), 5, showWatchdogDetailsOk, x, w);
        }

        function showWatchdogDetailsOk(x, w) {
            if (x == 2) {
                amtstack.Delete('AMT_AgentPresenceWatchdog', { 'DeviceID': w['DeviceID'] }, PullWatchdog);
            }
        }

        function AddWatchdog() {
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input id=wgname style=float:right;width:240px maxlength=16 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px>' + "Nome" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=wgguid style=float:right;width:240px maxlength=36 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px title="' + "Genera DeviceID casuale" + '">' + addLink("ID del dispositivo", 'GenerateWatchdogGuid()') + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=wgstart style=float:right;width:240px maxlength=8 placeholder=3600 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px>' + "Avvio (secondi)" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=wgtimeout style=float:right;width:240px maxlength=8 placeholder=60 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px>' + "Timeout (secondi)" + '</div></div>';
            setDialogMode(11, "Aggiungi cane da guardia", 3, AddWatchdogOk, x);
            AddWatchdogUpdate();
        }

        function GenerateWatchdogGuid() {
            var i, guid = '';
            for (i = 0; i < 16; i++) { guid += String.fromCharCode(random(255)); }
            Q('wgguid').value = guidToStr(rstr2hex(guid));
            AddWatchdogUpdate();
        }

        function AddWatchdogUpdate() {
            var ok = (Q('wgstart').value == '' || parseInt(Q('wgstart').value) > 0) && (Q('wgtimeout').value == '' || parseInt(Q('wgtimeout').value) > 0);
            var gc = 0, g = Q('wgguid').value.toLowerCase();
            for (var i = 0; i < g.length; i++) {
                var c = g.charCodeAt(i);
                if (c == 45) continue;
                if ((c >= 48 && c <= 57) || (c >= 97 && c <= 102)) { gc++; } else { ok = false; }
            }
            if (gc != 32) ok = false;
            QE('dlgOkButton', ok);
        }

        function AddWatchdogOk() {
            var timeout = Q('wgtimeout').value, startup = Q('wgstart').value;
            if (timeout == '') timeout = 60;
            if (startup == '') startup = 3600;
            var guid = btoa(hex2rstr(guidToStr(Q('wgguid').value.replace(/-/g, '')).replace(/-/g, '')));
            var wdog = { 'CreationClassName': 0, 'DeviceID': guid, 'StartupInterval': startup, 'SystemCreationClassName': 0, 'SystemName': 0, 'TimeoutInterval': timeout, 'MonitoredEntityDescription': Q('wgname').value };
            amtstack.Create('AMT_AgentPresenceWatchdog', wdog, AddWatchdogOk2);
        }

        function AddWatchdogOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Cane da guardia", "Impossibile aggiungere il watchdog, errore #" + status);
            } else {
                PullWatchdog();
            }
        }

        function addWatchdogAction(e, i) {
            var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];
            var x = '<table>';
            x += '<td style=width:180px>' + "A partire dal" + '<br>'
            for (var i in amtstack.WatchdogCurrentStates) {
                x += '<input id=wgsa' + i + ' type=checkbox onclick=addWatchdogActionUpdate()> ' + amtstack.WatchdogCurrentStates[i] + '<br />';
            }
            x += '<td>' + "Per" + '<br>'
            for (var i in amtstack.WatchdogCurrentStates) {
                x += '<input id=wgsb' + i + ' type=checkbox onclick=addWatchdogActionUpdate()> ' + amtstack.WatchdogCurrentStates[i] + '<br />';
            }
            x += '</table><br>' + "Esegui azione" + '<br><input id=wgsevent type=checkbox checked onclick=addWatchdogActionUpdate()>' + "Scrivi nel registro eventi" + '<br />';
            setDialogMode(11, "Aggiungi azione watchdog", 3, addWatchdogActionOk, x, w);
            addWatchdogActionUpdate();
            haltEvent(e);
        }

        function addWatchdogActionUpdate() {
            var tfrom = 0, tto = 0;
            for (var i in amtstack.WatchdogCurrentStates) {
                if (Q('wgsa' + i).checked == true) tfrom += parseInt(i);
                if (Q('wgsb' + i).checked == true) tto += parseInt(i);
            }
            QE('dlgOkButton', tfrom > 0 && tto > 0 && Q('wgsevent').checked == true);
        }

        function addWatchdogActionOk(b, w) {
            var tfrom = 0, tto = 0;
            for (var i in amtstack.WatchdogCurrentStates) {
                if (Q('wgsa' + i).checked == true) tfrom += parseInt(i);
                if (Q('wgsb' + i).checked == true) tto += parseInt(i);
            }
            amtstack.AMT_AgentPresenceWatchdog_AddAction(tfrom, tto, Q('wgsevent').checked, null, null, AddWatchdogActionResponse, null, 0, { 'DeviceID': w['DeviceID'] });
        }

        function AddWatchdogActionResponse(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Azione del cane da guardia", "Impossibile aggiungere l'azione del watchdog, errore #" + status);
            } else {
                PullWatchdog();
            }
        }

        function deleteWatchdogActions(e, i) {
            var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];
            setDialogMode(11, "Elimina azioni watchdog", 3, deleteWatchdogActionsOk, "Eliminare tutte le azioni per questo cane da guardia?", w);
            haltEvent(e);
        }

        function deleteWatchdogActionsOk(b, w) {
            amtstack.AMT_AgentPresenceWatchdog_DeleteAllActions(deleteWatchdogActionResponse, null, 0, { 'DeviceID': w['DeviceID'] });
        }

        function deleteWatchdogActionResponse(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Azione del cane da guardia", "Impossibile rimuovere le azioni del watchdog, errore #" + status);
            } else {
                PullWatchdog();
            }
        }

// ###END###{AgentPresence}
        
// ###BEGIN###{SystemDefense}

        //
        // SYSTEM DEFENSE PANEL
        //

        var xxSystemDefense = null;
        var xxSystemDefenceLinkedPolicy = {};
        var xxUpdatingDefenseStats = false;
        var xxFilterStatistics = [{}, {}]; // Wired and wireless interface stats
        var xxFilterStatisticsTimer = null;
        var xxFilterStatisticsTimerActive = false;

        var xxSystemDefenceFilterEthernetTypes = { 2048: "Tutti i pacchetti IP", 2054: "Tutti i pacchetti ARP" };
        var xxSystemDefenceFilterIPTypes = { 4: "IPv4", 6: "IPv6" };
        var xxSystemDefenceFilterDesc = { 0: "Consenti, conte", 1: "Lascia cadere, conta", 2: "Limite di velocità", 3: "permettere", 4: "Far cadere" };
        var xxSystemDefenceFilters = { 'HdrProtocolID': 1, 'HdrDestAddress': 2, 'HdrDestMask': 2, 'HdrSrcAddress': 2, 'HdrSrcMask': 2, 'HdrSrcPortStart': 1, 'HdrSrcPortEnd': 1, 'HdrDestPortStart': 1, 'HdrDestPortEnd': 1, 'HdrSrcAddressEndOfRange': 2, 'HdrDestAddressEndOfRange ': 2, 'TCPFlagsOn': 3, 'TCPFlagsOff': 3 };

        function PullSystemDefense() {
            amtFirstPull |= 4;
            amtstack.BatchEnum(null, ['AMT_SystemDefensePolicy', 'AMT_NetworkPortSystemDefensePolicy', 'AMT_Hdr8021Filter', 'AMT_IPHeadersFilter', 'AMT_NetworkFilter'], PullSystemDefenseResponse);
        }

        function PullSystemDefenseResponse(stack, name, responses, status) {
            if (status == 200) {
                xxSystemDefense = responses;
                updateSystemDefense();
                QV('go18', true); // Show System Defense Panel
                if (urlvars['norefresh']) { UpdateDefenseStats(); } // If norefresh is set, pull the system defense stats now.
            }
        }

        function updateSystemDefense() {
            if (xxSystemDefense == null) return;
            var x = '';

            // Get active policies
            xxSystemDefenceLinkedPolicy = {};
            for (var i in xxSystemDefense['AMT_NetworkPortSystemDefensePolicy'].responses) {
                var link = xxSystemDefense['AMT_NetworkPortSystemDefensePolicy'].responses[i];
                var a = +getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'DeviceID')['Value'].substring(27);
                var b = link['Dependent']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                var p = getItem(xxSystemDefense['AMT_SystemDefensePolicy'].responses, 'InstanceID', b);
                xxSystemDefenceLinkedPolicy[a] = p;
            }

            // Global System Defense settings
            x += TableStart();
            var policyname = ('<i>' + "Nessuna" + '</i>');
            if (xxSystemDefenceLinkedPolicy[0]) { policyname = xxSystemDefenceLinkedPolicy[0]['PolicyName']; }
            x += TableEntry("Politica cablata predefinita", addLink(policyname, 'changeDefaultPolicy(0)'));
            /*
            policyname = ('<i>' + "None" + '</i>');
            if (xxSystemDefenceLinkedPolicy[1]) { policyname = xxSystemDefenceLinkedPolicy[1]['PolicyName']; }
            x += TableEntry("Default Wireless Policy", addLink(policyname, 'changeDefaultPolicy(1)'));
            */

            // Filter Statistics
            for (var i = 0; i < 2; i++) {
                var f = xxFilterStatistics[i];
                for (var j in f) {
                    var c = f[j];
                    if (c == 1) c += " pacchetto"; else c += " pacchetti";
                    var jn = ((i==0)?"Cablata":"senza fili") + j;
                    x += TableEntry(jn, c);
                }
            }
            x += TableEnd();
            x += '<br>';

            x += TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px;border:0><br>' + "Gestisci le politiche di difesa del sistema Intel&reg; AMT." + '<br><br>';
            if (xxSystemDefense['AMT_SystemDefensePolicy'].responses.length == 0) {
                x += '<div style=padding-left:15px><i>' + "Nessuna politica di difesa del sistema trovata." + '</i></div><br>';
            } else {
                for (var i in xxSystemDefense['AMT_SystemDefensePolicy'].responses) {
                    var policy = xxSystemDefense['AMT_SystemDefensePolicy'].responses[i];
                    var desc = '';
                    if (policy['FilterCreationHandles']) {
                        policy['FilterCreationHandles'] = MakeToArray(policy['FilterCreationHandles']);
                        var c = policy['FilterCreationHandles'].length;
                        desc = ', ' + c + ' filter' + (c > 1?'s':'');
                    }
                    x += '<div class=itemBar onclick=showPolicyDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(policy['PolicyName']) + '</b>' + desc + '</div></div>';
                }
            }

            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gestisci i filtri di difesa del sistema Intel&reg; AMT." + '<br><br>';
            if (xxSystemDefense['AMT_Hdr8021Filter'].responses.length == 0 && xxSystemDefense['AMT_IPHeadersFilter'].responses.length == 0) {
                x += '<div style=padding-left:15px><i>' + "Nessun filtro di difesa del sistema trovato." + '</i></div><br>';
            } else {
                for (var i in xxSystemDefense['AMT_Hdr8021Filter'].responses) {
                    var filter = xxSystemDefense['AMT_Hdr8021Filter'].responses[i];
                    var desc = xxSystemDefenceFilterEthernetTypes[filter['HdrProtocolID8021']];
                    if (!desc) desc = "Tutto il protocollo Ethernet" + filter['HdrProtocolID8021'];
                    desc += ', ' + xxSystemDefenceFilterDesc[filter['FilterProfile']];
                    if (filter['FilterProfile'] == 2) { desc += " a" + filter['FilterProfileData'] + " pacchetto / sec"; }
                    if (filter['ActionEventOnMatch'] == true) desc += ", Evento in partita";
                    x += '<div class=itemBar onclick=showFilterDetails(0,' + i + ')><div style=padding-top:3px><b>' + (filter['FilterDirection'] == 0 ? '&#8592; ' : '&#8594; ') + EscapeHtml(filter['Name']) + '</b>, ' + desc + '</div></div>';
                }
                for (var i in xxSystemDefense['AMT_IPHeadersFilter'].responses) {
                    var filter = xxSystemDefense['AMT_IPHeadersFilter'].responses[i];
                    var desc = xxSystemDefenceFilterIPTypes[filter['HdrIPVersion']];
                    if (!desc) desc = "Tutto il protocollo Ethernet" + filter['HdrIPVersion'];
                    desc += ', ' + xxSystemDefenceFilterDesc[filter['FilterProfile']];
                    if (filter['FilterProfile'] == 2) { desc += " a" + filter['FilterProfileData'] + " pacchetto / sec"; }
                    if (filter['ActionEventOnMatch'] == true) desc += ", Evento in partita";
                    var filtercount = 0;
                    for (var j in xxSystemDefenceFilters) { if (filter[j]) filtercount++; }
                    if (filtercount > 0) desc += ', ' + filtercount + ' filter' + (filtercount>1?'s':'');
                    x += '<div class=itemBar onclick=showFilterDetails(1,' + i + ')><div style=padding-top:3px><b>' + (filter['FilterDirection'] == 0 ? '&#8592; ' : '&#8594; ') + EscapeHtml(filter['Name']) + '</b>, ' + desc + '</div></div>';
                }
            }
            x += '<br><td class=r1>' + TableEnd(AddRefreshButton('PullSystemDefense()') + /*AddButton("Update Stats", 'UpdateDefenseStats()') +*/ AddButton("Aggiungi filtro ...", 'AddDefenseFilter()') + AddButton("Aggiungi politica ...", 'AddDefensePolicy()'));

            QH('id_TableSystemDefense', x);

            if (xxFilterStatisticsTimer == null) {
                xxFilterStatisticsTimerActive = false;
                if (!urlvars['norefresh']) {
                    UpdateDefenseStats();
                    xxFilterStatisticsTimer = setInterval(UpdateDefenseStats, 5000);
                }
            }
        }

        function StopDefenseStatsTimer() {
            if (xxFilterStatisticsTimer != null) { clearInterval(xxFilterStatisticsTimer); xxFilterStatisticsTimer = null; }
            xxFilterStatisticsTimerActive = false;
        }

        function UpdateDefenseStats(n) {
            if (!n && xxFilterStatisticsTimerActive == true) { return; }
            xxFilterStatisticsTimerActive = true;
            var network = n?n:0;
            if (xxSystemDefenceLinkedPolicy[network]) {
                var eref = '<a:Address></a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_EthernetPort</w:ResourceURI><w:SelectorSet><w:Selector Name="DeviceID">Intel(r) AMT Ethernet Port ' + network + '</w:Selector></w:SelectorSet></a:ReferenceParameters>';
                amtstack.AMT_SystemDefensePolicy_UpdateStatistics(eref, false, UpdateDefenseStats2, network, 0, { 'InstanceID': xxSystemDefenceLinkedPolicy[network]['InstanceID'] });
            } else {
                // No active policy, stop the timer
                xxFilterStatistics[network] = {};
                StopDefenseStatsTimer();
            }
        }

        function UpdateDefenseStats2(stack, name, responses, status, network) {
            if (status == 200) {
                amtstack.Enum('AMT_ActiveFilterStatistics', UpdateDefenseStats3, network);
            } else {
                StopDefenseStatsTimer();
            }
        }

        function UpdateDefenseStats3(stack, name, responses, status, network) {
            var count = 0;
            if (status == 200) {
                xxFilterStatistics[network] = {};
                for (var i in responses) {
                    var readcount = responses[i]['ReadCount'];
                    // var matched = responses[i]['FilterMatched'];
                    var name = getItem(responses[i]['Dependent']['ReferenceParameters']['SelectorSet']['Selector'][1]['Value']['EndpointReference']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'Name')['Value'];
                    xxFilterStatistics[network][name] = readcount;
                    count++;
                }
                updateSystemDefense();
            }
            xxFilterStatisticsTimerActive = false;
            // If there is no statistics, stop the timer
            if (count == 0) { StopDefenseStatsTimer(); } // TODO: Change this to allow for wireless
        }

        function changeDefaultPolicy(network) {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><select id=policySelection style=float:right;width:266px><option value=-1>' + "Nessuna";
            for (var i in xxSystemDefense['AMT_SystemDefensePolicy'].responses) { x += '<option value=' + i + ((xxSystemDefenceLinkedPolicy[network] && xxSystemDefense['AMT_SystemDefensePolicy'].responses[i]['InstanceID'] == xxSystemDefenceLinkedPolicy[network]['InstanceID']) ? ' selected' : '') + '>' + xxSystemDefense['AMT_SystemDefensePolicy'].responses[i]['PolicyName']; }
            x += '</select><div style=padding-top:4px>' + "Politica di default" + '</div></div>';
            setDialogMode(11, "Politica di difesa del sistema predefinita", 3, changeDefaultPolicyOk, x, network);
        }

        function changeDefaultPolicyOk(button, network) {
            var i = Q('policySelection').value;
            var oldpolicy = xxSystemDefenceLinkedPolicy[network];
            if (oldpolicy) { amtstack.Delete('AMT_NetworkPortSystemDefensePolicy', '<w:SelectorSet><w:Selector Name="Antecedent"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_EthernetPort</w:ResourceURI><w:SelectorSet><w:Selector Name="CreationClassName">CIM_EthernetPort</w:Selector><w:Selector Name="DeviceID">Intel(r) AMT Ethernet Port ' + network + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector><w:Selector Name="Dependent"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SystemDefensePolicy</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + oldpolicy['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector></w:SelectorSet>', ((i == -1) ? PullSystemDefense : function () { })); }

            if (i >= 0) {
                var policy = xxSystemDefense['AMT_SystemDefensePolicy'].responses[i];
                var eref = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_EthernetPort</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="DeviceID">' + "Porta Ethernet Intel (r) AMT" + ' ' + network + '</Selector></SelectorSet></ReferenceParameters>';
                var pref = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SystemDefensePolicy</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + policy['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>';
                amtstack.Create('AMT_NetworkPortSystemDefensePolicy', { 'Antecedent': eref, 'Dependent': pref }, changeDefaultPolicyOk2);
            }
        }

        function changeDefaultPolicyOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Politica di difesa del sistema predefinita", "Impossibile impostare la politica, errore" + status);
            } else {
                PullSystemDefense();
            }
        }

        function AddDefenseFilter() {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input id=filtername style=float:right;width:260px maxlength=16 onkeyup=AddDefenseFilterUpdate()><div style=padding-top:4px>' + "Nome" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filtertype style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=0>' + "Filtro pacchetti IP Ethernet" + '<option value=1>' + "Filtro pacchetti Ethernet ARP" + '<option value=2>' + "Filtro pacchetti IPv4" + '<option value=3>' + "Filtro pacchetti IPv6" + '</select><div style=padding-top:4px>' + "genere" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=ipfilterdiv><input id=ipfilter style=float:right;width:260px placeholder=\"' + "Regole opzionali" + '\" onkeyup=AddDefenseFilterUpdate()><div style=padding-top:4px>' + "Regole di corrispondenza" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filterdir style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=0>' + "In uscita / Trasmissione" + '<option value=1>' + "Inbound / Ricevi" + '</select><div style=padding-top:4px>' + "Direzione" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filterprofile style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=0>' + "Consenti, conte" + '<option value=1>' + "Lascia cadere, conta" + '<option value=2>' + "Limite di tariffa" + '<option value=3>' + "permettere" + '<option value=4>' + "Far cadere" + '</select><div style=padding-top:4px>' + "Azione" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=filterdatadiv><input id=filterdata style=float:right;width:260px maxlength=8 onkeyup=AddDefenseFilterUpdate()><div style=padding-top:4px>' + "Pacchetti / secondo" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filteraction style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=false>' + "Fare niente" + '<option value=1>' + "Evento in partita" + '</select><div style=padding-top:4px>' + "Registro eventi" + '</div></div>';
            setDialogMode(11, "Aggiungi filtro di difesa del sistema", 3, AddDefenseFilterOk, x);
            AddDefenseFilterUpdate();
        }

        function AddDefenseFilterOk() {
            if (Q('filtertype').value <= 1) {
                // Add Ethernet IP or ARP filter
                var protocol = (Q('filtertype').value == 0) ? 2048 : 2054; // IP : ARP
                var filter = { 'InstanceID ': 0, 'Name': Q('filtername').value, 'CreationClassName': 0, 'SystemName': 0, 'SystemCreationClassName': 0, 'HdrProtocolID8021': protocol, 'FilterProfile': Q('filterprofile').value, 'FilterDirection': Q('filterdir').value, 'ActionEventOnMatch': Q('filteraction').value };
                if (Q('filterprofile').value == 2) filter['FilterProfileData'] = Q('filterdata').value;
                amtstack.Create('AMT_Hdr8021Filter', filter, AddDefenseFilterOk2);
            } else {
                // Add IPv4 or IPv6 Filter
                var protocol = (Q('filtertype').value == 2) ? 4 : 6; // IPv4 : IPv6
                var filter = { 'InstanceID ': 0, 'Name': Q('filtername').value, 'CreationClassName': 0, 'SystemName': 0, 'SystemCreationClassName': 0, 'HdrIPVersion': protocol, 'FilterProfile': Q('filterprofile').value, 'FilterDirection': Q('filterdir').value, 'ActionEventOnMatch': Q('filteraction').value };

                // Parse the filter string
                // https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=HTMLDocuments%2FWS-Management_Class_Reference%2FAMT_Hdr8021Filter.htm
                var filterstrs = Q('ipfilter').value.split(',');
                for (var i in filterstrs) {
                    var xx = filterstrs[i].indexOf('=');
                    var n = filterstrs[i].substring(0, xx);
                    var v = filterstrs[i].substring(xx + 1);
                    var t = xxSystemDefenceFilters[n];
                    if (!t) { n = "Hdr" + n; t = xxSystemDefenceFilters[n]; }
                    if (t) {
                        // TODO: Parse v (the value) based on the type t.
                        if (t == 2 && protocol == 4) {
                            // IPv4 address
                            var ipsplit = v.split('.');
                            if (ipsplit.length == 4) {
                                //filter[n] = btoa(String.fromCharCode(parseInt(ipsplit[0]), parseInt(ipsplit[1]), parseInt(ipsplit[2]), parseInt(ipsplit[3])));
                                //filter[n] = [ parseInt(ipsplit[0]), parseInt(ipsplit[1]), parseInt(ipsplit[2]), parseInt(ipsplit[3]) ];
                                filter[n] = rstr2hex(String.fromCharCode(parseInt(ipsplit[0]), parseInt(ipsplit[1]), parseInt(ipsplit[2]), parseInt(ipsplit[3])));
                            }
                        } else {
                            // Other values
                            filter[n] = v;
                        }
                    }
                }

                if (Q('filterprofile').value == 2) filter['FilterProfileData'] = Q('filterdata').value;
                amtstack.Create('AMT_IPHeadersFilter', filter, AddDefenseFilterOk2);
            }
        }

        function AddDefenseFilterUpdate() {
            var ok = Q('filtername').value.length > 0;
            if (ok && Q('filterprofile').value == 2) { var i = parseInt(Q('filterdata').value); ok = (i > 0 && i < 0xFFFFFFFF); }
            QE('idx_dlgOkButton', ok);
            QV('filterdatadiv', Q('filterprofile').value == 2);
            QV('ipfilterdiv', Q('filtertype').value >= 2);
        }

        function AddDefenseFilterOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Aggiungi filtro di difesa del sistema", "Impossibile aggiungere il filtro, errore #" + status);
            } else {
                PullSystemDefense();
            }
        }

        function showFilterDetails(t, i) {
            if (xxdialogMode) return;
            var desc, filter, type, tn;
            if (t == 0) {
                tn = 'AMT_Hdr8021Filter';
                type = "Ethernet Traffic";
                filter = xxSystemDefense[tn].responses[i];
                desc = xxSystemDefenceFilterEthernetTypes[filter['HdrProtocolID8021']];
                if (!desc) desc = "Tutto il protocollo Ethernet" + filter['HdrProtocolID8021'];
            } else {
                tn = 'AMT_IPHeadersFilter';
                type = "IP Traffic";
                filter = xxSystemDefense[tn].responses[i];
                desc = xxSystemDefenceFilterIPTypes[filter['HdrIPVersion']];
                if (!desc) desc = "Tutto il protocollo IP" + filter['HdrIPVersion'];
            }
            var x = '';
            x += addHtmlValue("Nome", EscapeHtml(filter['Name']));
            x += addHtmlValue("genere", type);
            x += addHtmlValue("Traffico corrispondente", desc);
            x += addHtmlValue("Direzione", filter['FilterDirection'] == 0 ? 'Outbound / Transmit' : 'Inbound / Receive');
            if (t == 1) {
                for (var j in xxSystemDefenceFilters) {
                    if (filter[j]) {
                        var n = j, v = filter[j], t = xxSystemDefenceFilters[j];
                        if (t == 2 && v.length == 4) { v = hex2rstr(v); v = v.charCodeAt(0) + '.' + v.charCodeAt(1) + '.' + v.charCodeAt(2) + '.' + v.charCodeAt(3); }
                        if (n.startsWith('Hdr')) n = n.substring(3);
                        x += addHtmlValue("Filtro" + n, v);
                    }
                }
            }
            x += addHtmlValue("Evento in partita", (filter['ActionEventOnMatch'] == true) ? 'Yes' : 'No');
            setDialogMode(11, "Filtro Ethernet #" + filter['InstanceID'], 5, showFilterDetailsOk, x, [tn, filter]);
        }

        function showFilterDetailsOk(b, tag) {
            if (b == 2) { amtstack.Delete(tag[0], tag[1], deleteDefenseFilter); }
        }

        function deleteDefenseFilter(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Rimuovi filtro", "Impossibile rimuovere il filtro, assicurarsi che non sia in uso.");
            } else {
                PullSystemDefense();
            }
        }

        var xxAddDefensePolicyFilters;
        function AddDefensePolicy() {
            if (xxdialogMode) return;
            xxAddDefensePolicyFilters = [];
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input id=policyname title="<policy name>:<policy precedence number>" style=float:right;width:260px maxlength=16 onkeyup=AddDefensePolicyUpdate()><div style=padding-top:4px>' + "Nome" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=policytx title="' + "Azione predefinita da eseguire per il traffico in uscita" + '" style=float:right;width:133px><option value=0>Allow<option value=1>' + "Far cadere" + '<option value=2>' + "Consenti, Conte" +'<option value=3>' + "Goccia, Conte" + '<option value=4>' + "Consenti, il conte, Evento" + '<option value=5>' + "Goccia, Conte, Evento" + '</select><select id=policyrx style=float:right;width:133px title="' + "Azione predefinita da eseguire per il traffico in entrata" + '"><option value=0>' + "permettere" + '<option value=1>' + "Far cadere" + '<option value=2>' + "Consenti, Conte" + '<option value=3>' + "Goccia, Conte" + '<option value=4>' + "Consenti, il conte, Evento" + '<option value=5>' + "Goccia, Conte, Evento" + '</select><div style=padding-top:4px>' + "TX / RX predefinito" + '</div></div>';
            x += '<div id=policyFilters></div>';
            if (xxSystemDefense['AMT_Hdr8021Filter'].responses.length > 0 || xxSystemDefense['AMT_IPHeadersFilter'].responses.length > 0) {
                x += '<div style=height:26px;margin-top:4px><div style=float:right><select id=xfilter style=width:186px>';
                for (var i in xxSystemDefense['AMT_Hdr8021Filter'].responses) {
                    var filter = xxSystemDefense['AMT_Hdr8021Filter'].responses[i];
                    x += '<option value=' + filter['InstanceID'] + '>' + filter['Name'];
                }
                for (var i in xxSystemDefense['AMT_IPHeadersFilter'].responses) {
                    var filter = xxSystemDefense['AMT_IPHeadersFilter'].responses[i];
                    x += '<option value=' + filter['InstanceID'] + '>' + filter['Name'];
                }
                x += '</select><input id=addFilterButton type=button value=Add style=width:80px onclick=addFilterButton()></div><div style=padding-top:4px>' + "Aggiungi filtro" + '</div></div>';
            }
            setDialogMode(11, "Aggiungi politica di difesa del sistema", 3, AddDefensePolicyOk, x);
            AddDefensePolicyUpdate();
        }

        function addFilterButton() {
            if (xxAddDefensePolicyFilters.indexOf(Q('xfilter').value) >= 0) return;
            xxAddDefensePolicyFilters.push(Q('xfilter').value);
            AddDefensePolicyUpdate();
        }

        function removeFilterButton(h) {
            xxAddDefensePolicyFilters.splice(h, 1);
            AddDefensePolicyUpdate();
        }

        function AddDefensePolicyUpdate() {
            var ok = Q('policyname').value.split(':')[0].length > 0;
            QE('idx_dlgOkButton', ok);
            if (xxAddDefensePolicyFilters.length == 0) {
                QH('policyFilters', '<br><i>' + "Questa politica non contiene filtri." + '</i><br><br>');
            } else {
                var x = '';
                for (var i in xxAddDefensePolicyFilters) {
                    x += '<div class=itemBar style=margin-right:0><div style=float:right>' + AddButton2("Rimuovere", 'removeFilterButton(' + i + ')') + '</div><div style=padding-top:3px;max-width:260px;overflow:hidden><b>' + GetFilterById(xxAddDefensePolicyFilters[i])['Name'] + '</b></div></div>';
                }
                QH('policyFilters', x);
            }
        }

        // TODO: Once loaded, we could make a table of "handle -> filter" where both filter types are mixed-in. Could make things simpler/smaller?
        // We would only have one table to loop instead of two at a few places. This function would be removed completely.
        function GetFilterById(h) {
            for (var i in xxSystemDefense['AMT_Hdr8021Filter'].responses) { var filter = xxSystemDefense['AMT_Hdr8021Filter'].responses[i]; if (filter['InstanceID'] == h) return filter; }
            for (var i in xxSystemDefense['AMT_IPHeadersFilter'].responses) { var filter = xxSystemDefense['AMT_IPHeadersFilter'].responses[i]; if (filter['InstanceID'] == h) return filter; }
        }

        function AddDefensePolicyOk() {
            var tx = Q('policytx').value;
            var rx = Q('policyrx').value;
            var pri = 0;
            var n = Q('policyname').value.split(':');
            if (n.length == 2) pri = parseInt(n[1]);
            var filter = { 'InstanceID ': 0, 'PolicyName': n[0], 'PolicyPrecedence': pri, 'TxDefaultCount': (tx > 1), 'TxDefaultDrop': (tx % 2 == 1), 'TxDefaultMatchEvent': (tx > 3), 'RxDefaultCount': (rx > 1), 'RxDefaultDrop': (rx % 2 == 1), 'RxDefaultMatchEvent': (rx > 3) };
            if (xxAddDefensePolicyFilters.length > 0) filter['FilterCreationHandles'] = xxAddDefensePolicyFilters;
            amtstack.Create('AMT_SystemDefensePolicy', filter, AddDefensePolicyOk2);
        }

        function AddDefensePolicyOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Aggiungi politica di difesa del sistema", "Impossibile aggiungere la politica, errore #" + status);
            } else {
                PullSystemDefense();
            }
        }

        function showPolicyDetails(i) {
            if (xxdialogMode) return;
            var policy = xxSystemDefense['AMT_SystemDefensePolicy'].responses[i];
            var x = '';
            x += addHtmlValue("Nome", EscapeHtml(policy['PolicyName']));
            if (policy['PolicyPrecedence'] != 0) x += addHtmlValue("Precedenza", policy['PolicyPrecedence']);

            var action = (policy['TxDefaultDrop'] == true) ? "Far cadere" : "permettere";
            if (policy['TxDefaultCount'] == true) action += ", Contare";
            if (policy['TxDefaultMatchEvent'] == true) action += ", Evento";
            x += addHtmlValue("Azione TX predefinita", action);

            action = (policy['RxDefaultDrop'] == true) ? 'Drop' : 'Allow';
            if (policy['RxDefaultCount'] == true) action += ', Count';
            if (policy['RxDefaultMatchEvent'] == true) action += ', Event';
            x += addHtmlValue("Azione RX predefinita", action);

            if (policy['FilterCreationHandles']) { for (var i in policy['FilterCreationHandles']) { x += addHtmlValue("Filtro n." + (+i + 1), GetFilterById(policy['FilterCreationHandles'][i])['Name']); } }

            setDialogMode(11, format("Politica #", policy['InstanceID'].substring(20)), 5, showPolicyDetailsOk, x, policy);
        }

        function showPolicyDetailsOk(b, tag) {
            if (b == 2) { amtstack.Delete('AMT_SystemDefensePolicy', tag, deleteDefensePolicy); }
        }

        function deleteDefensePolicy(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Rimuovi politica", "Impossibile rimuovere la politica, assicurarsi che non sia in uso.");
            } else {
                PullSystemDefense();
            }
        }

// ###END###{SystemDefense}

// ###BEGIN###{NetworkSettings}
// ###BEGIN###{Wireless}

        //
        // WIRELESS SETTINGS PANEL
        //

        var xxWireless;
        function PullWireless() {
            amtFirstPull |= 2;
            try { if (amtwirelessif == -1) return; } catch (e) { } // If the wireless adapter has no MAC, don't show this.
            // ###BEGIN###{!NetAuth}
            amtstack.BatchEnum('', ['*CIM_WiFiPortCapabilities', '*CIM_WiFiPort', '*CIM_WiFiEndpoint', 'CIM_WiFiEndpointSettings', '*AMT_WiFiPortConfigurationService'], processWireless);
            // ###END###{!NetAuth}
            // ###BEGIN###{NetAuth}
            amtstack.BatchEnum('', ['*CIM_WiFiPortCapabilities', '*CIM_WiFiPort', '*CIM_WiFiEndpoint', 'CIM_WiFiEndpointSettings', '*AMT_WiFiPortConfigurationService', 'CIM_IEEE8021xSettings'], processWireless);
            // ###END###{NetAuth}
        }

        function wifiRefresh() { if (!xxdialogMode) PullWireless(); }

        var xxWifiState = { 3: "Disabilitato", 32768: "Abilitato in S0", 32769: "Abilitato in S0, Sx / AC" };
        var xxRadioState = 	{ 2: "Acceso, connesso", 3: "via", 6: "Acceso, disconnesso" };
        var xxWifiAuthenticationMethod = { 1: "Altro", 2: "Aperto", 3: "Chiave condivisa", 4: "WPA PSK", 5: "WPA IEEE 802.1x", 6: "WPA2 PSK", 7: "WPA2 IEEE 802.1x", 32768: "WPA3 SAE IEEE 802.1x", 32769: "WPA3 OWE IEEE 802.1x" };
        var xxWifiEncryptionMethod = { 1: "Altro", 2: "WEP", 3: "TKIP-RC4", 4: "CCMP-AES", 5: "Nessuna" }; // For 2 & 5, AuthenticationMethod must be 2 or 3. For 3 & 4 AuthenticationMethod must be 4,5,6 or 7

        function processWireless(stack, name, responses, status) {
            if (status == 200) { xxWireless = responses; } else { xxWireless = undefined; }
            updateSystemStatus();
            showWirelessInfo();
        }

        function showWirelessInfo() {
            if (!xxWireless) return;
            var i, j, s = '', sc, x = '<br><h2>' + "Profili wireless" + '</h2>';
            if (!(xxWireless['CIM_WiFiPortCapabilities'].response)) return;

            // Show WIFI profiles sorted by priority
            x += TableStart2();
            x += '<tr><td class=r2 style=padding-left:15px><br>' + "Profili wireless che Intel&reg; AMT utilizzerà per la connettività di rete." + '<br><br>';
            s = 0;
            for(i = 0; i < 256; i++) {
                for (j in xxWireless['CIM_WiFiEndpointSettings'].responses) {
                    sc = xxWireless['CIM_WiFiEndpointSettings'].responses[j];
                    if (sc['AuthenticationMethod'] == 1) continue; // Skip "Endpoint User Settings"
                    if (sc['Priority'] == i) {
                        var details = '';
                        // ###BEGIN###{NetAuth}
                        var netAuthProfile = null, netAuthProtocols = ['EAP-TLS', 'EAP-TTLS/MSCHAPv2', 'PEAPv0/EAP-MSCHAPv2', 'PEAPv1/EAP-GTC', 'EAP-FAST/MSCHAPv2', 'EAP-FAST/GTC', 'EAP-MD5', 'EAP-PSK', 'EAP-SIM', 'EAP-AKA', 'EAP-FAST/TLS'];
                        if (xxWireless['CIM_IEEE8021xSettings'].responses) {
                            for (var k in xxWireless['CIM_IEEE8021xSettings'].responses) {
                                if (xxWireless['CIM_IEEE8021xSettings'].responses[k]['ElementName'] == sc['ElementName']) { netAuthProfile = xxWireless['CIM_IEEE8021xSettings'].responses[k]; }
                            }
                        }
                        if (netAuthProfile) { details = ', ' + netAuthProtocols[netAuthProfile['AuthenticationProtocol']]; }
                        // ###END###{NetAuth}
                        x += '<div class=itemBar onclick=showWifiDetails(' + j + ')><div style=float:right>' + EscapeHtml(sc['SSID']) + ', ' + xxWifiAuthenticationMethod[sc['AuthenticationMethod']] + ', ' + xxWifiEncryptionMethod[sc['EncryptionMethod']] + details + ' &nbsp; ';
                        if (xxAccountAdminName) x += AddButton2("Rimuovere", 'wifiRemoveButton(\"' + j + '\")');
                        x += '</div><div style=padding-top:3px><b>' + EscapeHtml(sc['ElementName']) + '</b></div></div>';
                        s++;
                    }
                }
            }
            if (s == 0) x += '<i>' + "Nessun profilo wireless presente" + '</i><br>';

            // End of table
            x += '<br><td class=r2>';
            if (xxAccountAdminName) x += TableEnd(AddButton("Nuovo profilo", 'showWifiNewProfile()')); else x += TableEnd('');
            QH('id_TableWifi2', x + '<br>');
        }
        
        function showWifiStateDlg() {
            if (xxdialogMode) return;
            var s = '';
            for (var i in xxWifiState) { s += '<label><input type=radio name=d11 id=wl' + i + ' value=' + i + ' ' + ((xxWireless['CIM_WiFiPort'].response['EnabledState'] == i)?'checked':'') + '>' + xxWifiState[i] + '</label><br>'; }
            setDialogMode(11, "Stato wireless", 3, wifiStateDlg, s);
        }

        function wifiStateDlg() { amtstack.CIM_WiFiPort_RequestStateChange( document.querySelector('input[name=d11]:checked').value, null, function() { amtstack.Get('CIM_WiFiPort', function(stack, name, response, status) { if (status == 200) { xxWireless['CIM_WiFiPort'].response = response.Body; showWirelessInfo(); } } ); } ); }

        function showWifiSyncDlg() {
            if (xxdialogMode) return;
            var s = '';
            s += '<label><input type=radio name=d11 id=wl0 value=0 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 0) ? 'checked' : '') + '>' + "Disabilitato" + '</label><br>';
            s += '<label><input type=radio name=d11 id=wl0 value=1 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 1) ? 'checked' : '') + '>' + "Abilitato" + '</label><br>';
            setDialogMode(11, "Local Profile Sync", 3, showWifiSyncDlgEx, s);
        }

        function showWifiSyncDlgEx() {
            var k = Clone(xxWireless['AMT_WiFiPortConfigurationService'].response);
            k['localProfileSynchronizationEnabled'] = document.querySelector('input[name=d11]:checked').value;
            amtstack.Put('AMT_WiFiPortConfigurationService', k, function () { amtstack.Get('AMT_WiFiPortConfigurationService', function (stack, name, response, status) { if (status == 200) { xxWireless['AMT_WiFiPortConfigurationService'].response = response.Body; showWirelessInfo(); } }); });
        }
        
        function showUefiWifiCoExDlg() {
            if (xxdialogMode) return;
            var s = '';
            s += '<label><input type=radio name=d12 value=0 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled'] == false)?'checked':'') + '>Disabled</label><br>'; 
            s += '<label><input type=radio name=d12 value=1 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled'] == true)?'checked':'') + '>Enabled</label><br>'; 
            setDialogMode(11, "UEFI Wifi CoEx Profile Sharing", 3, UefiWifiCoExDlg, s);
        }
        
        function UefiWifiCoExDlg() {
            var wifiportcfgsvc = Clone(xxWireless['AMT_WiFiPortConfigurationService'].response);
            wifiportcfgsvc["UEFIWiFiProfileShareEnabled"]=document.querySelector('input[name=d12]:checked').value;
            amtstack.Put('AMT_WiFiPortConfigurationService', wifiportcfgsvc, function(stack, name, responses, status) {if (status == 200) {PullWireless()}})
        }

        function showWifiDetails(h) {
            if (xxdialogMode) return;
            var i, sc = xxWireless['CIM_WiFiEndpointSettings'].responses[h], x = '<div style=text-align:left>';
            x += addHtmlValue("Nome del profilo", EscapeHtml(sc['ElementName']));
            x += addHtmlValue("SSID", EscapeHtml(sc['SSID']));
            x += addHtmlValue("Autenticazione", xxWifiAuthenticationMethod[sc['AuthenticationMethod']]);
            x += addHtmlValue("crittografia", xxWifiEncryptionMethod[sc['EncryptionMethod']]);
            x += addHtmlValue("Priorità", sc['Priority']);
            // ###BEGIN###{NetAuth}
            var netAuthProfile = null, netAuthProtocols = ['EAP-TLS', 'EAP-TTLS/MSCHAPv2', 'PEAPv0/EAP-MSCHAPv2', 'PEAPv1/EAP-GTC', 'EAP-FAST/MSCHAPv2', 'EAP-FAST/GTC', 'EAP-MD5', 'EAP-PSK', 'EAP-SIM', 'EAP-AKA', 'EAP-FAST/TLS'];
            if (xxWireless['CIM_IEEE8021xSettings'].responses) {
                for (var k in xxWireless['CIM_IEEE8021xSettings'].responses) {
                    if (xxWireless['CIM_IEEE8021xSettings'].responses[k]['ElementName'] == sc['ElementName']) { netAuthProfile = xxWireless['CIM_IEEE8021xSettings'].responses[k]; }
                }
            }
            if (netAuthProfile) {
                x += '<div style="width:100%;border-bottom:1px solid #000;margin-bottom:5px;margin-top:5px">802.11x</div>'
                x += addHtmlValue("Autenticazione", netAuthProtocols[netAuthProfile['AuthenticationProtocol']]);
                if (netAuthProfile['Domain']) { x += addHtmlValue("Domain", EscapeHtml(netAuthProfile['Domain'])); }
                if (netAuthProfile['Username']) { x += addHtmlValue("Nome utente", EscapeHtml(netAuthProfile['Username'])); }
            }
            // ###END###{NetAuth}
            x += '</div>';
            messagebox("Profilo wireless", x);
        }

        function wifiRemoveButton(h) {
            if (xxdialogMode) return;
            var sc = xxWireless['CIM_WiFiEndpointSettings'].responses[h];
            QH('id_dialogMessage', format("Rimuovere il profilo wireless \"{0}\"?", sc['ElementName']));
            setDialogMode(1, "Profilo wireless", 3, function () { removeWifiButtonEx(h) });
        }

        function removeWifiButtonEx(h) {
            var sc = xxWireless['CIM_WiFiEndpointSettings'].responses[h];
            amtstack.Delete('CIM_WiFiEndpointSettings', { InstanceID: sc['InstanceID'] }, removeWifiEntryResponse, 0, 1);
        }

        function removeWifiEntryResponse(stack, name, response, status, tag) {
            if (methodcheck(response)) return;
            // ###BEGIN###{!NetAuth}
            amtstack.BatchEnum('', ['CIM_WiFiEndpointSettings'], function (stack, name, responses, status) {
                if (status == 200) {
                    xxWireless['CIM_WiFiEndpointSettings'].responses = responses['CIM_WiFiEndpointSettings'].responses;
                    showWirelessInfo();
                }
            });
            // ###END###{!NetAuth}
            // ###BEGIN###{NetAuth}
            amtstack.BatchEnum('', ['CIM_WiFiEndpointSettings', 'CIM_IEEE8021xSettings'], function (stack, name, responses, status) {
                if (status == 200) {
                    xxWireless['CIM_WiFiEndpointSettings'].responses = responses['CIM_WiFiEndpointSettings'].responses;
                    xxWireless['CIM_IEEE8021xSettings'].responses = responses['CIM_IEEE8021xSettings'].responses;
                    showWirelessInfo();
                }
            });
            // ###END###{NetAuth}
        }

        function showWifiNewProfile() {
            if (xxdialogMode) return;
            var x = '';
            for (i = 1; i < 256; i++) {
                var t = 1;
                for (j in xxWireless['CIM_WiFiEndpointSettings'].responses) { if (xxWireless['CIM_WiFiEndpointSettings'].responses[j]['Priority'] == i) t = 0; }
                if (t) { x += '<option value='+ i +'>'+ i; } // Option is a tag that is self closing.
            }
            QH('idx_d12pri', x);

            // ###BEGIN###{NetAuth}
            // Set certificates
            var clientcertoptions = '<option value=-1>' + EscapeHtml("Nessuna") + '</option>', servercertoptions = '<option value=-1>' + EscapeHtml("Nessuna") + '</option>';
            for (var i in xxCertificates) {
                if (xxCertificates[i].TrustedRootCertficate) {
                    servercertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                } else if (xxCertificates[i].XPrivateKey) {
                    clientcertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                }
            }
            QH('idx_d12clientcert', clientcertoptions);
            QH('idx_d12servercert', servercertoptions);
            // ###END###{NetAuth}

            var authOptions = '';
            // ###BEGIN###{NetAuth}
            authOptions += '<option value=32769>' + "WPA3 OWE IEEE 802.1x" + '</option>';
            authOptions += '<option value=32768>' + "WPA3 SAE IEEE 802.1x" + '</option>';
            authOptions += '<option value=7>' + "WPA2 IEEE 802.1x" + '</option>';
            authOptions += '<option value=5>' + "WPA IEEE 802.1x" + '</option>';
            // ###END###{NetAuth}
            authOptions += '<option value=6>' + "WPA2 PSK" + '</option>';
            authOptions += '<option value=4>' + "WPA PSK" + '</option>';
            QH('idx_d12auth', authOptions);

            idx_d12auth.value = 6;
            idx_d12enc.value = 4;
            idx_d12name.value = idx_d12ssid.value = idx_d12password1.value = idx_d12password2.value = '';

            setDialogMode(12, "Aggiungi profilo wireless", 3, function () { addWifiProfile() });
            updateWifiDialog();
        }

        function addWifiProfile() {
            var sc, netAuthSettingsClientCert, netAuthSettingsServerCaCert;
            var v = {
                '__parameterType': 'instance',
                '__namespace': amtstack.CompleteName('CIM_WiFiEndpointSettings'),
                'ElementName': idx_d12name.value,
                'InstanceID': 'Intel(r) AMT:WiFi Endpoint Settings ' + idx_d12name.value,
                'AuthenticationMethod': idx_d12auth.value,
                'EncryptionMethod': idx_d12enc.value,
                'SSID': idx_d12ssid.value,
                'Priority': idx_d12pri.value
            };
            if ((idx_d12auth.value == 4) || (idx_d12auth.value == 6)) { v['PSKPassPhrase'] = idx_d12password1.value; }
            // ###BEGIN###{NetAuth}
            if ((idx_d12auth.value == 5) || (idx_d12auth.value == 7) || (idx_d12auth.value == 32768) || (idx_d12auth.value == 32769)) {
                sc = {
                    '__parameterType': 'instance',
                    '__namespace': amtstack.CompleteName('CIM_IEEE8021xSettings'),
                    'ElementName': '8021x-' + idx_d12name.value,
                    'InstanceID': '8021x-' + idx_d12name.value,
                    'ActiveInS0': (Q('idx_d12activeins0').value == 1),
                    'AuthenticationProtocol': Q('idx_d12protocol').value
                };
                if (Q('idx_d12roamingidentity').value != '') { sc['RoamingIdentity'] = Q('idx_d12roamingidentity').value; }
                if (Q('idx_d12servername').value != '') { sc['ServerCertificateName'] = Q('idx_d12servername').value; sc['ServerCertificateNameComparison'] = Q('idx_d12servernamecompare').value; }
                if (Q('idx_d12username').value != '') { sc['Username'] = Q('idx_d12username').value; }
                if (Q('idx_d12password').value != '') { sc['Password'] = Q('idx_d12password').value; }
                if (Q('idx_d12domain').value != '') { sc['Domain'] = Q('idx_d12domain').value; }
                if (Q('idx_d12protocol').value > 3) { sc['ProtectedAccessCredential'] = Q('idx_d12pac').value; sc['PACPassword'] = Q('idx_d12pacpassword').value; }
                if (parseInt(Q('idx_d12clientcert').value) >= 0) { netAuthSettingsClientCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d12clientcert').value)]['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>'; }
                if (parseInt(Q('idx_d12servercert').value) >= 0) { netAuthSettingsServerCaCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d12servercert').value)]['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>'; }
            }
            // ###END###{NetAuth}

            console.log('wifiepsettinginput', JSON.sstringify(v, null, 2));
            console.log('netAuthProfile', JSON.sstringify(sc, null, 2));
            console.log('netAuthSettingsClientCert', netAuthSettingsClientCert);
            console.log('netAuthSettingsServerCaCert', netAuthSettingsServerCaCert);

            amtstack.AMT_WiFiPortConfigurationService_AddWiFiSettings(
				{
				    '__parameterType': 'reference',
				    '__resourceUri': amtstack.CompleteName('CIM_WiFiEndpoint'),
				    'Name': 'WiFi Endpoint 0'
				}, v,
				sc, netAuthSettingsClientCert, netAuthSettingsServerCaCert, removeWifiEntryResponse
			);
        }

        function updateWifiDialog() {
            var r = true;
            var a = idx_d12auth.value;
            var e = idx_d12enc.value;
            //QV('id_d12e2', a < 4);
            //QV('id_d12e3', a > 3);
            //QV('id_d12e4', a > 3);
            //QV('id_d12e5', a < 4);
            if (a < 4 && (e == 3 || e == 4)) { idx_d12enc.value = 2; }
            if (a > 3 && (e == 2 || e == 5)) { idx_d12enc.value = 3; }
            if ((a == 32768) || (a == 32769)) { idx_d12enc.value = 4; }
            QV('idx_d12pass', (a == 4) || (a == 6));
            QV('idx_d12netauth', (a == 5) || (a == 7) || (a == 32768) || (a == 32769));

            // Check if there is already a profile with this name
            for (var j in xxWireless['CIM_WiFiEndpointSettings'].responses) { if (xxWireless['CIM_WiFiEndpointSettings'].responses[j]['ElementName'] == idx_d12name.value) { r = false; } }
            if ((idx_d12name.value.length == 0) && (idx_d12ssid.value.length == 0)) { r = false; }
            if (((a == 4) || (a == 6)) && ((idx_d12password1.value.length < 8) || (idx_d12password1.value.length > 63) || (idx_d12password1.value != idx_d12password2.value))) { r = false; }

            QE('idx_dlgOkButton', r);

            // ###BEGIN###{NetAuth}
            updateNetAuthDialog();
            // ###END###{NetAuth}
        }

        // ###BEGIN###{NetAuth}
        function updateNetAuth2Dialog() {
            QV('idx_d12servernamecomparediv', (Q('idx_d12servernamediv').value != ''));
            QV('idx_d12pacdiv', (Q('idx_d12protocol').value > 3));
            QV('idx_d12pacpassworddiv', (Q('idx_d12protocol').value > 3));
        }
        // ###END###{NetAuth}

// ###END###{Wireless}
// ###BEGIN###{NetAuth}

        //
        // 802.1x SETTINGS
        //

        function editNetAuthProfile() {
            if (xxdialogMode) return;

            // Set certificates
            var clientcertoptions = '<option value=-1>' + EscapeHtml("Nessuna") + '</option>', servercertoptions = '<option value=-1>' + EscapeHtml("Nessuna") + '</option>';
            for (var i in xxCertificates) {
                if (xxCertificates[i].TrustedRootCertficate) {
                    servercertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                } else if (xxCertificates[i].XPrivateKey) {
                    clientcertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                }
            }
            QH('idx_d27clientcert', clientcertoptions);
            QH('idx_d27servercert', servercertoptions);

            // Set profile
            var sc = amtsysstate['AMT_8021XProfile'].responses.Body;
            Q('idx_d27enabled').value = sc['Enabled'] ? 1 : 0;
            Q('idx_d27activeins0').value = (sc['ActiveInS0'] ? 1 : 0);
            Q('idx_d27pxetimeout').value = sc['PxeTimeout'];
            if (sc['Enabled']) {
                Q('idx_d27protocol').value = sc['AuthenticationProtocol'];
                Q('idx_d27roamingidentity').value = sc['RoamingIdentity'] ? sc['RoamingIdentity'] : '';
                Q('idx_d27servername').value = sc['ServerCertificateName'] ? sc['ServerCertificateName'] : '';
                Q('idx_d27servernamecompare').value = sc['ServerCertificateNameComparison'] ? sc['ServerCertificateNameComparison'] : 0;
                Q('idx_d27username').value = sc['Username'] ? sc['Username'] : '';
                Q('idx_d27password').value = sc['Password'] ? sc['Password'] : '';
                Q('idx_d27domain').value = sc['Domain'] ? sc['Domain'] : '';
                Q('idx_d27pac').value = sc['ProtectedAccessCredential'] ? sc['ProtectedAccessCredential'] : '';
                Q('idx_d27pacpassword').value = sc['PACPassword'] ? sc['PACPassword'] : '';
                var scInstanceId = -1, ccInstanceId = -1;
                if (sc['ServerCertificateIssuer']) { scInstanceId = sc['ServerCertificateIssuer']['ReferenceParameters']['SelectorSet']['Selector']['Value']; }
                if (sc['ClientCertificate']) { ccInstanceId = sc['ClientCertificate']['ReferenceParameters']['SelectorSet']['Selector']['Value']; }
                for (var i in xxCertificates) {
                    if (xxCertificates[i]['InstanceID'] == scInstanceId) { Q('idx_d27servercert').value = i; }
                    if (xxCertificates[i]['InstanceID'] == ccInstanceId) { Q('idx_d27clientcert').value = i; }
                }
            }
            setDialogMode(27, "802.1x Profile", 3, function () { setNetAuthProfile() });
            updateNetAuthDialog();
        }

        function updateNetAuthDialog() {
            QV('idx_d27protocoldiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27servernamediv', Q('idx_d27enabled').value == 1);
            QV('idx_d27servernamecomparediv', (Q('idx_d27enabled').value == 1) && (Q('idx_d27servername').value != ''));
            QV('idx_d27domaindiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27usernamediv', Q('idx_d27enabled').value == 1);
            QV('idx_d27passworddiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27roamingidentitydiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27pacdiv', (Q('idx_d27enabled').value == 1) && (Q('idx_d27protocol').value > 3));
            QV('idx_d27pacpassworddiv', (Q('idx_d27enabled').value == 1) && (Q('idx_d27protocol').value > 3));
            QV('idx_d27clientcertdiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27servercertdiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27activeins0div', Q('idx_d27enabled').value == 1);
            QV('idx_d27pxetimeoutdiv', Q('idx_d27enabled').value == 1);
        }

        function setNetAuthProfile() {
            var sc = Clone(amtsysstate['AMT_8021XProfile'].responses.Body);
            sc['Enabled'] = (Q('idx_d27enabled').value == 1);
            if (sc['Enabled']) {
                sc['ActiveInS0'] = (Q('idx_d27activeins0').value == 1);
                sc['AuthenticationProtocol'] = Q('idx_d27protocol').value;
                if (Q('idx_d27roamingidentity').value != '') { sc['RoamingIdentity'] = Q('idx_d27roamingidentity').value; } else { delete sc['RoamingIdentity']; }
                if (Q('idx_d27servername').value != '') {
                    sc['ServerCertificateName'] = Q('idx_d27servername').value;
                    sc['ServerCertificateNameComparison'] = Q('idx_d27servernamecompare').value;
                } else {
                    delete sc['ServerCertificateName'];
                    delete sc['ServerCertificateNameComparison'];
                }
                if (Q('idx_d27username').value != '') { sc['Username'] = Q('idx_d27username').value; } else { delete sc['Username']; }
                if (Q('idx_d27password').value != '') { sc['Password'] = Q('idx_d27password').value; } else { delete sc['Password']; }
                if (Q('idx_d27domain').value != '') { sc['Domain'] = Q('idx_d27domain').value; } else { delete sc['Domain']; }
                if (Q('idx_d27protocol').value > 3) {
                    sc['ProtectedAccessCredential'] = Q('idx_d27pac').value;
                    sc['PACPassword'] = Q('idx_d27pacpassword').value;
                } else {
                    delete sc['ProtectedAccessCredential'];
                    delete sc['PACPassword'];
                }
                if (parseInt(Q('idx_d27clientcert').value) >= 0) { sc['ClientCertificate'] = '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d27clientcert').value)]['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters>'; } else { delete sc['ClientCertificate']; }
                if (parseInt(Q('idx_d27servercert').value) >= 0) { sc['ServerCertificateIssuer'] = '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d27servercert').value)]['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters>'; } else { delete sc['ServerCertificateIssuer']; }
                sc['PxeTimeout'] = Q('idx_d27pxetimeout').value;
            }
            amtstack.Put('AMT_8021XProfile', sc, setNetAuthProfileEx);
        }

        function setNetAuthProfileEx(stack, name, response, status) {
            if (status == 200) {
                amtsysstate['AMT_8021XProfile'].responses.Body = amtsysstate['AMT_8021XProfile'].response = response.Body;
                updateSystemStatus();
            } else {
                if (response.Header['WsmanError']) {
                    messagebox("802.1x Error", response.Header['WsmanError'].replace(/_/g, ' '));
                } else {
                    messagebox("802.1x Error", "Error, Status = " + status);
                }
            }
        }

// ###END###{NetAuth}
// ###END###{NetworkSettings}

// ###BEGIN###{HardwareInfo}
        //
        // HARDWARE INFORMATION PANEL
        //

        function PullHardware() {
            amtstack.BatchEnum('', ['*CIM_ComputerSystemPackage', 'CIM_SystemPackaging', '*CIM_Chassis', 'CIM_Chip', '*CIM_Card', '*CIM_BIOSElement', 'CIM_Processor', 'CIM_PhysicalMemory', 'CIM_MediaAccessDevice', 'CIM_PhysicalPackage', '*CIM_Battery'], processHardware);
            amtFirstPull |= 1; // Set the hardware info bit on, indicates we are pulling this information.
        }

        // http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
        var DMTFCPUStatus = ["Sconosciuto", "Abilitato", "Disabilitato dall'utente", "Disabilitato dal BIOS (errore POST)", "Inattivo", "Altro"];
        var DMTFMemType = ["Sconosciuto", "Altro", "DRAM", "DRAM sincrona", "Cache DRAM", "EDO", "EDRAM", "VRAM", "SRAM", "RAM", "rom", "Veloce", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM", "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR-2", "BRAM", "FB-DIMM", "DDR3", "FBD2", "DDR4", "LPDDR", "LPDDR2", "LPDDR3", "LPDDR4"];
        var DMTFMemFormFactor = ['', "Altro","Sconosciuto","SIMM","SORSO","Patata fritta","TUFFO","ZIP","Carta proprietaria","DIMM","TSOP","Fila di patatine","RIMM","SODIMM","SRIMM","FB-DIM"];
        var DMTFProcFamilly = { // Page 46 of DMTF document
            191: "Processore Intel&reg; Core &trade; 2 Duo",
            192: "Processore Intel&reg; Core &trade; 2 Solo",
            193: "Processore Intel&reg; Core &trade; 2 Extreme",
            194: "Processore Intel&reg; Core &trade; 2 Quad",
            195: "Processore mobile Intel&reg; Core &trade; 2 Extreme",
            196: "Processore mobile Intel&reg; Core &trade; 2 Duo",
            197: "Processore mobile Intel&reg; Core &trade; 2 Solo",
            198: "Processore Intel&reg; Core &trade; i7",
            199: "Processore Intel&reg; Celeron&reg; dual-core" };

        var HardwareInventory;
        function processHardware(stack, name, responses, status) {
            if (status != 200) return;

            var i, x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            HardwareInventory = responses;
            QV('go2', true); // Show "Hardware Information" on left panel

            // ###BEGIN###{!FileSaver}
            x += TableEnd('<div>&nbsp;' + AddRefreshButton('PullHardware(1)') + " Le informazioni sull'hardware vengono raccolte all'avvio del sistema.");
            // ###END###{!FileSaver}
            // ###BEGIN###{FileSaver}
            x += TableEnd('<div>&nbsp;' + AddRefreshButton('PullHardware(1)') + AddButton("Salva...", 'SaveHardwareLog()') + " Le informazioni sull'hardware vengono raccolte all'avvio del sistema.");
            // ###END###{FileSaver}

            var ba = responses['CIM_Chassis'].response;
            var bb = responses['CIM_Card'].response;
            var v = responses['CIM_BIOSElement'].response['SoftwareElementID'];
            
            x += '<br><h2>' + "piattaforma" + '</h2>';
            x += FullTable({"Modello di computer":ba['Model'], "fabbricante":ba['Manufacturer'], "Versione":ba['Version'], "Numero di serie":ba['SerialNumber'], "ID di sistema":guidToStr(responses['CIM_SystemPackaging'].responses[0]['PlatformGUID']).toLowerCase()}, '');

            x += '<br><h2>' + "zoccolo" + '</h2>';
            x += FullTable({"fabbricante":bb['Manufacturer'], "Nome del prodotto":bb['Model'], "Versione":bb['Version'], "Numero di serie":bb['SerialNumber'], "Etichetta delle risorse":bb['Tag'], "Sostituibile?":(bb['CanBeFRUed']==true)?'Yes':'No' },'');
            
            x += '<br><h2>' + "BIOS" + '</h2>';
            x += FullTable({"venditore":responses['CIM_BIOSElement'].response['Manufacturer'], "Versione":v, "Data di rilascio":new Date(responses['CIM_BIOSElement'].response['ReleaseDate']['Datetime']).toLocaleDateString('en', {timeZone:'UTC'})},'');
            
            x += '<br>';
            for (i in responses['CIM_Processor'].responses) {
                var p = responses['CIM_Processor'].responses[i];
                var q = responses['CIM_Chip'].responses[i]; // This is a shortcut, we assume that the first entries in CIM_Chip are the processors, in the same order.
                x += '<h2>' + "Processore" + ' ' + (parseInt(i) + 1) + '</h2>';
                x += FullTable({"fabbricante":trademarks(q['Manufacturer']), "Famiglia":DMTFProcFamilly[p['Family']], "Versione":trademarks(q['Version']), "Velocità massima della presa":p['MaxClockSpeed'] + " MHz", "Stato":DMTFCPUStatus[p['CPUStatus']]},'');
            }
            x += '<br>';

            for (i in responses['CIM_PhysicalMemory'].responses) {
                var m = responses['CIM_PhysicalMemory'].responses[i];
                x += '<h2>' + "Modulo di memoria" + ' ' + (+i + 1) + '</h2>';
                x += FullTable({"Etichetta bancaria":m['BankLabel'], "fabbricante":m['Manufacturer'], "Numero di serie":m['SerialNumber'], "Dimensione":parseInt(m['Capacity'] / 0x100000) + " MB", "Fattore di forma":DMTFMemFormFactor[m['FormFactor']], "genere":DMTFMemType[m['MemoryType']], "Etichetta delle risorse":m['Tag'], "Numero parte":m['PartNumber']},'');
            }
            x += '<br>';

            for (i in responses['CIM_MediaAccessDevice'].responses) {
                var m = responses['CIM_MediaAccessDevice'].responses[i];
                var n = responses['CIM_PhysicalPackage'].responses[+i + 1]; // This is a shortcut, we assume CIM_PhysicalPackage is the same as CIM_MediaAccessDevice except for the first entry.
                x += '<h2>' + "Supporti di memorizzazione" + ' ' + (parseInt(i) + 1) + '</h2>';
                x += FullTable({"Modello":n['Model'],"Numero di serie":(n['SerialNumber']==''?'Unknown':n['SerialNumber']), "Dimensione":parseInt(Math.round(m['MaxMediaSize'] * 1000 / 0x100000)) + " MB"},'');
            }
            x += '<br>';

            if (responses['CIM_Battery'].response != null) {
                var battInfo = null;
                for (i in responses['CIM_PhysicalPackage'].responses) { if (responses['CIM_PhysicalPackage'].responses[i].PackageType == 11) { battInfo = responses['CIM_PhysicalPackage'].responses[i]; } }
                if (battInfo != null) {
                    x += '<h2>' + "Battery" + '</h2>';
                    var battdate = new Date(battInfo['ManufactureDate']['Datetime']).toDateString()
                    var batttype = ["Altro", "Sconosciuto", "Lead Acid", "Nickel Cadmium", "Nickel Metal Hydride", "Lithium-ion", "Zinc air", "Lithium Polymer"][responses['CIM_Battery'].response['Chemistry']];
                    var batt = { "Device name": responses['CIM_Battery'].response['DeviceID'], "fabbricante": battInfo['Manufacturer'], "Manufacture date": battdate, "Numero di serie": battInfo['SerialNumber'], "genere": batttype, "Design capacity": responses['CIM_Battery'].response['DesignCapacity'] + ' ' + "mWatt-hours", "Design voltage": responses['CIM_Battery'].response['DesignVoltage'] + ' ' + "mVolts" };
                    if (battInfo['OtherIdentifyingInfo']) { batt["Other Info"] = battInfo['OtherIdentifyingInfo']; }
                    x += FullTable(batt, '');
                }
            }
            x += '<br>';

            QH('id_TableSysInfo', x);
            updateSystemStatus();
        }

        // ###BEGIN###{FileSaver}
        function SaveHardwareLog() {
            if (!xxdialogMode && HardwareInventory) SaveJsonFile('IntelAmtHardware', 'hardware', "Informazioni sull'hardware Intel AMT", HardwareInventory);
        }
        // ###END###{FileSaver}

// ###END###{HardwareInfo}

        //
        // POWER POLICY
        //

        var AmtSystemPowerSchemes = null;
        function PullPowerPolicy() { amtstack.Enum('AMT_SystemPowerScheme', powerPolicyResponse); }
        function powerPolicyResponse(stack, name, response, status) { AmtSystemPowerSchemes = response; updateSystemStatus(); }

        function showPowerPolicyDlg(currentguid) {
            if (xxdialogMode) return;
            var s = '';

            // Now find the name of the power schema in the AMT_SystemPowerScheme table
            for (var j = 0; j < AmtSystemPowerSchemes.length; j++) {
                var selected = ((AmtSystemPowerSchemes[j]['SchemeGUID'] == currentguid)?' checked':'');
                s += '<input type=radio name=powerpolicy value=\"' + AmtSystemPowerSchemes[j]['InstanceID'] + '\" ' + selected + '>' + AmtSystemPowerSchemes[j]['Description'] + '<br>';
            }

            setDialogMode(11, "Intel&reg; AMT Power Policy", 3, showPowerPolicyDlgOk, s);
        }

        function showPowerPolicyDlgOk() {
            var id = null, i = 0, e = document.getElementsByTagName('input');
            for (; i < e.length; i++) { if (e[i].name == 'powerpolicy' && e[i].checked) { id = e[i].value; } }
            amtstack.AMT_SystemPowerScheme_SetPowerScheme(showPowerPolicyDlgOkDone, id);
        }

        function showPowerPolicyDlgOkDone(stack, name, response, status) { if (status == 200) PullSystemStatus(); }

        //
        // USER INFORMATION PANEL
        //

        var xxAccountAdminName, xxAccountRealmInfo, xxAccountEnabledInfo = {}, xxAccountFetch, showHiddenAccounts = false;

        function PullUserInfo() {
            xxAccountFetch = 1;
            delete xxAccountAdminName;
            xxAccountRealmInfo = {};
            amtstack.AMT_AuthorizationService_GetAdminAclEntry(getAdminAclEntryResponse);
            amtstack.AMT_AuthorizationService_EnumerateUserAclEntries(1, enumerateUserAclEntriesResponse);
        }

        function getAdminAclEntryResponse(stack, name, response, status) {
            if (status != 200) return;
            xxAccountRealmInfo[-1] = { 'AccessPermission': 999, 'DigestUsername': response.Body['Username'], 'Realms':null };
            xxAccountAdminName = response.Body['Username'];
            updateAccounts();
        }

        function enumerateUserAclEntriesResponse(stack, name, response, status) {
            if (status != 200) return;
            //if (errcheck(status, stack)) return;
            methodcheck(response);
            QV('go11', true); // Show "User Accounts" on left panel
            xxAccountFetch = response.Body['Handles'].length;
            for (var i in response.Body['Handles']) {
                var h = response.Body['Handles'][i];
                amtstack.AMT_AuthorizationService_GetAclEnabledState(h, getAclEnabledStateResponse, h);
                amtstack.AMT_AuthorizationService_GetUserAclEntryEx(h, getUserAclEntryExResponse, h);
            }
            updateAccounts();
        }

        function getUserAclEntryExResponse(stack, name, response, status, tag) {
            xxAccountFetch--;
            //if (errcheck(status, stack)) return;
            //methodcheck(response);
            if (status == 200) { // Sometimes Intel AMT will just freak out on this call, if it's the case, just carry on.
                response.Body['Handle'] = tag;
                if (!response.Body['Realms']) response.Body['Realms'] = [];
                else if (!Array.isArray(response.Body['Realms'])) response.Body['Realms'] = [response.Body['Realms']]; // If "Realms" is not an array, it's because it's just one realm. Fix is so it's an array of one.
                xxAccountRealmInfo[tag] = response.Body;
                updateAccounts();
            }
        }

        function getAclEnabledStateResponse(stack, name, response, status, tag) {
            //if (errcheck(status, stack)) return;
            if (status == 200) { // Sometimes Intel AMT will just freak out on this call, if it's the case, just carry on.
                xxAccountEnabledInfo[tag] = response.Body;
                updateAccounts();
            }
        }

        function setAclEnabledStateResponse(stack, name, response, status, tag) {
            if (errcheck(status, stack)) return;
            methodcheck(response);
            amtstack.AMT_AuthorizationService_GetAclEnabledState(tag, getAclEnabledStateResponse, tag);
        }

        function updateAccounts() {
            if (xxAccountFetch > 0) return;
            var x = TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gestire gli account utente Intel&reg; AMT per questo computer." + '<br><br>';
            for (var i in xxAccountRealmInfo) {
                var r = xxAccountRealmInfo[i], name, hidden = false, state = 0;
                if (r['DigestUsername']) { name = r['DigestUsername']; hidden = (name[0] == '$' && name[1] == '$'); } else { name = GetSidString(atob(r['KerberosUserSid'])); }
                if (xxAccountEnabledInfo[i] && name != '$$OsAdmin') { state = (xxAccountEnabledInfo[i]['Enabled'] == true)?1:2; }
                if (showHiddenAccounts || !hidden) {
                    var rb = '';
                    if (r['AccessPermission'] != 999) {
                        if (state == 2) { rb += "Disabilitato,"; }
                        var rc = 0;
                        for (i in r['Realms']) { if (amtstack.RealmNames[r["Realms"][i]] != '') { rc++; } } // Count only realms that have a name, removing reserved realms.
                        if (r['Realms'].indexOf(20) >= 0) rb += "Sindaco,";
                        if (r['Realms'].indexOf(3) >= 0) { rb += "Amministratore"; } else { if (rc == 1) { rb += "1 regno"; } else { rb += rc + " regni"; } }
                    } else {
                        rb += "Amministratore";
                        r['Handle'] = -1;
                    }
                    x += '<div class=itemBar onclick=showUserDetails(' + r['Handle'] + ')><div style=float:right>';
                    if (state > 0 && xxAccountAdminName) x += ' ' + AddButton2((state == 1?'Disable':'Enable'), 'changeAccountStateButton(event,' + r['Handle'] + ',' + state + ')');
                    if (!hidden && xxAccountAdminName) x += ' ' + AddButton2("Modificare...", 'changeAccountButton(event,' + r['Handle'] + ')');
                    x += '</div><div style=padding-top:3px;width:330px;float:left;overflow-x:hidden title="' + name + '"><b>' + name + '</b></div><div style=padding-top:3px>' + rb + '</div></div>';
                }
            }
            var y = '<div style=float:right;margin-right:8px><a title="' + "Attiva / disattiva account nascosti" + '" style=color:gray;cursor:pointer onclick=toggleAccountButton()>' + (showHiddenAccounts?'&#x25B2;':'&#x25BC;') + '</a></div><div>&nbsp;' + AddRefreshButton('xxAccountFetch=999;PullUserInfo()');
            if (xxAccountAdminName) y += AddButton("Nuovo account", 'newAccountButton()');
            x += '<br><td class=r1>' + TableEnd(y + '</div>');
            QH('id_TableUserAccounts', x);
        }

        function toggleAccountButton() {
            showHiddenAccounts = !showHiddenAccounts;
            updateAccounts();
        }

        function removeUserAclEntryResponse(stack, name, response, status, tag) {
            if (methodcheck(response)) return;
            PullUserInfo();
        }

        function changeAccountStateButton(e, h, s) {
            haltEvent(e);
            if (xxdialogMode) return;
            amtstack.AMT_AuthorizationService_SetAclEnabledState(h, (s==1?false:true), setAclEnabledStateResponse, h);
        }

        function changeAccountButton(e, h) {
            haltEvent(e);
            if (xxdialogMode) return;
            updateRealms(xxAccountRealmInfo[h]['Realms']);
            d2username.value = xxAccountRealmInfo[h]['DigestUsername'] ? xxAccountRealmInfo[h]['DigestUsername'] : GetSidString(atob(xxAccountRealmInfo[h]['KerberosUserSid']));
            d2password1.value = d2password2.value = '';
            d2permission.value = xxAccountRealmInfo[h]['AccessPermission'];
            setDialogMode(2, "Modifica account", ((h==-1)?3:7), function (button) { changeAccountButtonEx(h, button); }); // If handle is -1, only display OK/Cancel buttons, if not, also display delete button.
            updateAccountDialog();
        }

        function newAccountButton() {
            if (xxdialogMode) return;
            updateRealms([]);
            d2username.value = d2password1.value = d2password2.value = '';
            d2permission.value = 2;
            setDialogMode(2, "Nuovo account", 3, function () { changeAccountButtonEx(null, 1); });
            updateAccountDialog();
        }

        function changeAccountButtonEx(h, button) {
            if (button == 1) { // OK Button
                var realms = [], username = d2username.value, permission = d2permission.value, password = d2password1.value, sid = GetSidByteArray(Q('d2username').value), d = null;
                if (username.length == 0 || password != d2password2.value) { messagebox("Errore dell'account", "Parametri non validi"); return; }
                if (sid == null) { d = window.btoa(rstr_md5(username + ":" + amtsysstate['AMT_GeneralSettings'].response['DigestRealm'] + ":" + password)); } else { username = null; sid = btoa(sid); }
                if (h != -1) { for (var y in amtstack.RealmNames) { if (((amtstack.RealmNames[y]) || (y == 3)) && Q('rx' + y).checked) { realms.push(y); } } }
                if (h == null) { amtstack.AMT_AuthorizationService_AddUserAclEntryEx(username, d, sid, permission, realms, userAclEntryExResponse); }
                else if (h == -1) { amtstack.AMT_AuthorizationService_SetAdminAclEntryEx(username, d, userAclEntryExResponse); }
                else { amtstack.AMT_AuthorizationService_UpdateUserAclEntryEx(h, username, d, sid, permission, realms, userAclEntryExResponse); }
            }
            if (button == 2) { // Delete Button
                amtstack.AMT_AuthorizationService_RemoveUserAclEntry(h, removeUserAclEntryResponse);
            }
        }

        function userAclEntryExResponse(stack, name, response, status, tag) { if (methodcheck(response)) return; PullUserInfo(); }
        function updateRealms(r) {
            QV('id_d2permissions', r != null);
            if (r != null) {
                var x = '<li><label><input type=checkbox onchange=updateAccountDialog() id=rx3' + ((r.indexOf(3) >= 0)?' checked':'') + '>' + "Amministratore" + '</label></li><hr />';
                for (var y in amtstack.RealmNames) { var c = ''; if (r.indexOf(parseInt(y)) >= 0) c = ' checked'; if (amtstack.RealmNames[y]) x += '<li><label><input type=checkbox onchange=updateAccountDialog() id=rx' + y + c + '>' + amtstack.RealmNames[y] + '</label></li>'; }
                QH('id_d2realms', x);
            }
        }

        function updateAccountDialog() {
            var ok = true;
            if (Q('id_d2permissions').style.display != 'none') { ok = false; for (var y in amtstack.RealmNames) { if (((amtstack.RealmNames[y]) || (y == 3)) && Q('rx' + y).checked) { ok = true; } } }
            if (ok) { ok = ((d2username.value.length > 0) && (passwordcheck(d2password1.value)) && (d2password1.value == d2password2.value)); }
            QE('idx_dlgOkButton', ok);
        }

        var xxUserPermissions = ["Solo locale" , "Solo rete", "Tutti (locali e di rete)"];
        function showUserDetails(h) {
            if (xxdialogMode) return;
            var a = xxAccountRealmInfo[h], x = '<div style=text-align:left>';
            var i, n = a['DigestUsername'];
            if (!n) n = GetSidString(atob(a['KerberosUserSid']));
            x += addHtmlValue("Nome", n);
            if (xxAccountEnabledInfo[h]) { x += addHtmlValue("Stato", ((xxAccountEnabledInfo[h]['Enabled'] == true)?"Abilitato":"Disabilitato")); }
            if (n == xxAccountAdminName) {
                x += addHtmlValue("Autorizzazione", "Amministratore");
            } else {
                x += addHtmlValue("Autorizzazione", xxUserPermissions[a['AccessPermission']]);
                var y = '';
                if (a['Realms'].indexOf(3) >= 0) {
                    y = "Amministratore";
                    if (a['Realms'].indexOf(20) >= 0) y += ", Revisore contabile";
                } else {
                    for (i in xxAccountRealmInfo[h]['Realms']) {
                        if (amtstack.RealmNames[a['Realms'][i]] != '') { // Remove blank reserved realms
                            if (y.length > 0) y += ",";
                            y += amtstack.RealmNames[a['Realms'][i]];
                        }
                    }
                }
                if (y.length == 0) y = "Nessuna";
                x += addHtmlValue("Realms", '') + '<b>' + y + '</b>';
            }
            x += '</div>';
            messagebox("account" + n, x);
        }

        //
        // WSMAN BROWSER PANEL
        //

        // ###BEGIN###{WsmanBrowser}
        function wsmanQuery() {
            QH('id_wsresults', '');
            var selections = getSelectedOptions(Q('id_QuerySelect')), selections2 = [];
            for (var x in selections) { if (QS('WSB-' + selections[x]).display == '') selections2.push(selections[x]); }
            if (selections2.length == 0) return;
            QE('id_p12querybutton', false);
            if (selections2 && selections2.length > 0) { amtstack.BatchEnum("Browser", selections2, browserResponse, null, true); } // This is the only BatchEnum where we want to continue and get an answer even if one of the calls fails.
        }

        function browserResponse(stack, name, responses, status) {
            QE('id_p12querybutton', true);
            var h = '';
            for (var r in responses) {
                var response = responses[r];
                h += '<h2>' + r + '</h2><div style=margin-left:20px>';
                if (response.status == 200) { if (response.responses.length == 0) { h += ('<br>' + "(Vuoto)"); } else { h += ObjectToString(response.responses).replace(/Intel\(r\)/g, 'Intel&reg'); } } else { h += '<br><div style=color:red>' + "Errore n." + response.status + '</div>'; }
                h += '</div><br>';
            }
            QH('id_wsresults', h);
        }

        function wsmanFilter() {
            var filter = idx_browserFilter.value.toLowerCase();
            for (var w in AllWsman) { QV('WSB-' + AllWsman[w], filter == '' || AllWsman[w].toLowerCase().indexOf(filter) >= 0); }
        }
        // ###END###{WsmanBrowser}

        //
        // Remote Terminal
        //

        // ###BEGIN###{Terminal}
        function connectTerminal() {
            if (!terminal) return;
            if (terminal.State == 0) {
                // ###BEGIN###{ComputerSelector}
                terminal.digestRealmMatch = amtstack.wsman.comm.digestRealm;
                // ###END###{ComputerSelector}
                // ###BEGIN###{Mode-MeshCentral2}
                terminal.tlsv1only = amtstack.wsman.comm.tlsv1only;
                terminal.Start(currentMeshNode._id, 16994, '*', '*', 0);
                // ###END###{Mode-MeshCentral2}
                // ###BEGIN###{ComputerSelector}
                // ###BEGIN###{Mode-NodeWebkit}

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) {
                    terminal.Start(currentcomputer._id, 0, 'x', 'x', 0, wsstack.comm, meshCentralServer);
                } else {
                    // ###END###{MeshServerConnect}
                    var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls'])
                    terminal.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                    // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}

                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{!Mode-NodeWebkit}
                terminal.tlsv1only = amtstack.wsman.comm.tlsv1only;
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls'])
                terminal.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                // ###END###{!Mode-NodeWebkit}
                // ###END###{ComputerSelector}
                // ###BEGIN###{Mode-Firmware}
                terminal.Start();
                // ###END###{Mode-Firmware}
            } else {
                terminal.Stop();
            }
        }

        function onTerminalStateChange(terminal, state) {
            // console.log("onTerminalStateChange: " + state);
            idx_connectbutton2.value = (state == 0) ? "Collegare" : "Disconnect";
            Q('id_termstatus').textContent = StatusStrs[state];
            QE('id_tpastebutton', state == 3);
            // ###BEGIN###{!Mode-NodeWebkit}
            QE('TermWD', state == 3);
            // ###END###{!Mode-NodeWebkit}
            switch (state) {
                case 0:
                    terminal.m.TermResetScreen();
                    terminal.m.TermDraw();
                    if (xxdialogMode == 3) setDialogMode();
                    // ###BEGIN###{Mode-MeshCentral2}
                    QV('termRecordIcon', false);
                    // ###END###{Mode-MeshCentral2}
                    if (terminal.disconnectCode == 2) { // BUSY
                        messagebox("Remote Terminal", "The remote device is busy, a session may already be open.");
                    } else if (terminal.disconnectCode == 3) { // UNSUPPORTED
                        messagebox("Remote Terminal", "The device indicated that this type of connection of not supported.");
                    }
                    break;
                case 3:
                    // ###BEGIN###{Mode-MeshCentral2}
                    if (terminal.serverIsRecording == true) { QV('termRecordIcon', true); }
                    // ###END###{Mode-MeshCentral2}
                    break;
            }
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }

        function termPaste() { terminal.m.TermSendKeys(d3pastetextarea.value); return false; }
        function termSendKey(k) { terminal.m.TermSendKey(k); return false; }
        function termSendKeys() { var k = Q('termkeys').value; if (k < 1000) { termSendKey(k); } else { terminal.m.TermHandleKeyDown({ which: k - 889, repeat: false }); } }

        // ###BEGIN###{TerminalSize}
        function termToggleSize() {
            if (terminal.m.width == 80) {
                Q('id_tsizebutton').value = '100x30';
                terminal.m.Init(100, 30);
            } else {
                Q('id_tsizebutton').value = '80x25';
                terminal.m.Init(80, 25);
            }
        }
        // ###END###{TerminalSize}

        // ###BEGIN###{Terminal-Enumation-All}
        var terminalEmulations = ["Terminale UTF8", "ASCII esteso", "Intel ASCII"];
        function termToggleType() {
            terminal.m.terminalEmulation = (terminal.m.terminalEmulation + 1) % 3;
            Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
        }
        // ###END###{Terminal-Enumation-All}

        // ###BEGIN###{Terminal-FxEnumation-All}
        function termToggleFx() {
            Q('id_tfxkeysbutton').value = ["Intel (F10 = ESC + [OM)", "Alternativo (F10 = ESC + 0)", "VT100 + (F10 = ESC + [OY)"][terminal.m.fxEmulation = (terminal.m.fxEmulation + 1) % 3];
        }
        // ###END###{Terminal-FxEnumation-All}

        function termToggleCr() {
            if (terminal.m.lineFeed == '\r\n') {
                Q('id_tcrbutton').value = "LF";
                terminal.m.lineFeed = '\n';
            } else {
                Q('id_tcrbutton').value = "CR + LF";
                terminal.m.lineFeed = '\r\n';
            }
        }

        // ###BEGIN###{FileSaver}
        function terminalCaptureToggle(e) {
            if (xxdialogMode) return;
            // ###BEGIN###{TerminalReplay}
            if ((e != null) && (e.shiftKey == true)) { terminalReplay(); return; }
            if (terminalReplayTimer != null) { return; }
            // ###END###{TerminalReplay}
            if (terminal.m.capture == undefined) {
                terminal.m.capture = ''; // Start terminal capture
                // ###BEGIN###{!Mode-NodeWebkit}
                idx_terminalCaptureButton.value = "Stop Capture";
                // ###END###{!Mode-NodeWebkit}
            } else {
                if (terminal.m.capture.length > 0) {
                    var n = 'TerminalCapture', d = new Date();
                    if (amtsysstate) { n += '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
                    n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
                    // ###BEGIN###{!Mode-NodeWebkit}
                    saveAs(data2blob(terminal.m.capture), n + '.txt');
                    delete terminal.m.capture;
                    idx_terminalCaptureButton.value = "Avvia acquisizione";
                    // ###END###{!Mode-NodeWebkit}
                    // ###BEGIN###{Mode-NodeWebkit}
                    var chooser = document.createElement('input');
                    chooser.setAttribute('type', 'file');
                    chooser.setAttribute('nwsaveas', n + '.txt');
                    chooser.addEventListener('change', function() {
                        require('fs').writeFile(this.value, terminal.m.capture, function () { });
                        delete terminal.m.capture;
                    }, false);
                    chooser.click();
                    // ###END###{Mode-NodeWebkit}
                } else {
                    delete terminal.m.capture;
                    // ###BEGIN###{!Mode-NodeWebkit}
                    idx_terminalCaptureButton.value = "Avvia acquisizione";
                    // ###END###{!Mode-NodeWebkit}
                }
            }
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        // ###BEGIN###{TerminalReplay}
        function terminalReplay() {
            if (xxdialogMode) return;
            if (terminalReplayTimer != null) {
                clearInterval(terminalReplayTimer); terminalReplayBuffer = null; terminalReplayBufferPtr = 0; terminalReplayTimer = null;
                // ###BEGIN###{Mode-NodeWebkit}
                NW_SetupMainMenu(currentView);
                // ###END###{Mode-NodeWebkit}
            } else {
                setDialogMode(11, "Apri Terminal Capture", 3, terminalReplayEx, '<input id=termCaptureFile type=file style=width:100% accept=.txt>');
            }
        }

        function terminalReplayEx() {
            var x = Q('termCaptureFile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = terminalReplayEx2;
            reader.readAsBinaryString(x.files[0]);
        }

        var terminalReplayBuffer = null;
        var terminalReplayBufferPtr = 0;
        var terminalReplayTimer = null;
        function terminalReplayEx2(file) {
            terminal.m.TermResetScreen();
            if (terminalReplayTimer != null) { clearInterval(terminalReplayTimer); terminalReplayTimer = null; }
            terminalReplayBufferPtr = 0;
            terminalReplayBuffer = file.target.result;
            terminalReplayTimer = setInterval(terminalReplayEx3, 5);
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }

        function terminalReplayEx3() {
            var len = ((terminalReplayBufferPtr - 1) < terminalReplayBuffer.length) ? 2 : 1;
            var x = terminalReplayBuffer.substring(terminalReplayBufferPtr, terminalReplayBufferPtr + len);
            terminal.m.ProcessData(x);
            terminalReplayBufferPtr += len;
            if (terminalReplayBufferPtr >= terminalReplayBuffer.length) {
                clearInterval(terminalReplayTimer); terminalReplayBuffer = null; terminalReplayBufferPtr = 0; terminalReplayTimer = null;
                // ###BEGIN###{Mode-NodeWebkit}
                NW_SetupMainMenu(currentView);
                // ###END###{Mode-NodeWebkit}
            }
        }

        // ###END###{TerminalReplay}

        function terminal_FileSelectHandler(e) {
            haltEvent(e);
            if (terminal.State != 3 || e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = terminal_onSetupBinRead;
            reader.readAsText(e.dataTransfer.files[0]);
        }

        function terminal_onSetupBinRead(file) {
            d3pastetextarea.value = file.target.result;
            setDialogMode(3, "Incolla", 3, termPaste)
        }

        // ###END###{Terminal}

        //
        // Remote Desktop
        //

        // ###BEGIN###{Desktop}

        // ###BEGIN###{Desktop-Multi}
        var desktopScreenInfo = null;
        var desktopPollTimer = null;
        // ###END###{Desktop-Multi}
        // ###BEGIN###{DesktopInband}
        var webRtcDesktop = null;
        function webRtcDesktopReset() {
            if (webRtcDesktop == null) return;
            if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
            if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
            if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
            webRtcDesktop = null;
            // Switch back to hardware KVM
            desktop.m.hold(false);
            updateDesktopState();
            // ###BEGIN###{DesktopInbandFiles}
            p24files = null;
            p24downloadFileCancel() // If any downloads are in process, cancel them.
            p24uploadFileCancel(); // If any uploads are in process, cancel them.
            QV('go24', false); // Files
            if (currentView == 24) { go(14); }
            // ###END###{DesktopInbandFiles}
        }

        /*
        function webRtcDesktopProcessData(data) {
            console.log('WebRTC data, len = ' + data.length);
        }
        */
        // ###END###{DesktopInband}

        function connectDesktopButton(e) { desktop.disconnectCode = 0; connectDesktop(e); }

        var connectDesktopConsent = false;
        function connectDesktop(skipConsent) {
            if (!desktop || xxdialogMode) return;
            connectDesktopConsent = false; // TODO, this is not a good idea when calls are pending.
            if (desktop.State == 0) {
                // Check if user consent is needed
                if ((skipConsent !== true) && (amtversion > 5) && ((amtsysstate == null) || (amtsysstate != null) && (amtsysstate['IPS_OptInService'] != null) && (amtsysstate['IPS_OptInService'].response != null) && (amtsysstate['IPS_OptInService'].response['OptInRequired'] != 0))) {
                    connectDesktopConsent = true; amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1); return; // User consent always required, ask for it before KVM.
                }
                // Encoding Flags: 1 = RLE, 2 = 16bit, 4 = Gray, 8 = ZLib, 16 = 4bit Color
                desktop.m.useRLE = ((desktopsettings.encflags & 1) != 0);
                desktop.m.bpp = (desktopsettings.encflags & 2) ? 2 : 1;
                if ((amtversion > 15) && (amtsysstate != null) && (amtsysstate['IPS_KVMRedirectionSettingData'] != null) && (amtsysstate['IPS_KVMRedirectionSettingData'].response)) {
                    desktop.m.lowcolor = amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported'] && ((desktopsettings.encflags & 16) != 0);
                    desktop.m.graymode = amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported'] && ((desktopsettings.encflags & 4) != 0);
                    desktop.m.useZLib = amtsysstate['IPS_KVMRedirectionSettingData'].response['ZlibControlSupported'] && ((desktopsettings.encflags & 8) != 0);
                    desktop.m.decimationMode = ((amtsysstate['IPS_KVMRedirectionSettingData'].response['InitialDecimationModeForLowRes'] > 0) ? desktopsettings.decimationMode : 0);
                } else {
                    desktop.m.lowcolor = false;
                    desktop.m.graymode = false;
                    desktop.m.useZLib = false;
                    desktop.m.decimationMode = 0;
                }
                desktop.m.showmouse = desktopsettings.showmouse;
                desktop.m.onScreenSizeChange = center;
                // ###BEGIN###{ComputerSelector}
                desktop.digestRealmMatch = amtstack.wsman.comm.digestRealm;
                // ###END###{ComputerSelector}
                // ###BEGIN###{DesktopInband}
                desktop.m.onKvmData = function(x) {
                    //console.log('onKvmData (' + x.length + '): ' + x);
                    var data = null;
                    try { data = JSON.parse(x); } catch (e) {}
                    if ((data != null) && (data.action != null)) {
                        if (data.action == 'restart') {
                            // Clear WebRTC channel
                            webRtcDesktopReset();
                            desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
                        } else if ((data.action == 'present') && (webRtcDesktop == null)) {
                            // Setup WebRTC channel
                            webRtcDesktop = { platform: data.platform };
                            var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
                            if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
                            else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }

                            webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
                            webRtcDesktop.webchannel.onopen = function () {
                                // Switch to software KVM
                                if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
                                desktop.m.hold(true);
                                webRtcDesktop.webRtcActive = true;
                                webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
                                webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
                                if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
                                if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
                                webRtcDesktop.softdesktop.Start();
                                updateDesktopState();

                                // Check if we can get remote file access
                                // ###BEGIN###{DesktopInbandFiles}
                                QV('go24', true); // Files
                                downloadFile = null;
                                p24files = webRtcDesktop.softdesktop;
                                p24targetpath = '';
                                webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
                                webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
                                // ###END###{DesktopInbandFiles}
                            }
                            webRtcDesktop.webchannel.onclose = function (event) { if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); } webRtcDesktopReset(); }
                            webRtcDesktop.webrtc.onicecandidate = function (e) {
                                if (e.candidate == null) {
                                    desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
                                } else {
                                    webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
                                }
                            }
                            webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
                                if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
                            }
                            webRtcDesktop.webrtc.createOffer(function (offer) {
                                // Got the offer
                                webRtcDesktop.webrtcoffer = offer;
                                webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
                            }, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
                        } else if ((data.action == 'answer') && (webRtcDesktop != null)) {
                            // Complete the WebRTC channel
                            webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
                        }
                    }
                };
                if ((amtversion > 15) || urlvars['kvmext']) { desktop.m.kvmExtChanged = updateDesktopState; } else { desktop.m.kvmExtChanged = null; }
                // ###END###{DesktopInband}
                desktop.m.frameRateDelay = ((desktopsettings.limitFrameRate == true)?200:0);
                desktop.m.noMouseRotate = desktopsettings.noMouseRotate;
                desktop.m.ReverseMouseWheel = desktopsettings.reverseMouseWheel;
                // ###BEGIN###{Mode-MeshCentral2}
                desktop.tlsv1only = amtstack.wsman.comm.tlsv1only;
                desktop.Start(currentMeshNode._id, 16994, '*', '*', 0);
                // ###END###{Mode-MeshCentral2}
                // ###BEGIN###{ComputerSelector}
                // ###BEGIN###{Mode-NodeWebkit}

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) {
                    desktop.Start(currentcomputer._id, 0, 'x', 'x', 0, wsstack.comm, meshCentralServer);
                } else {
                // ###END###{MeshServerConnect}
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                if ((amtsysstate) && (amtsysstate['IPS_ScreenConfigurationService'] != null) && ((amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState'] & 1) != 0)) {
                    amtstack.IPS_ScreenConfigurationService_SetSessionState(Q('id_DeskSB').checked == true ? 1 : 0, 3, function (stack, name, responses, status) {
                        if (status != 200) { Q('id_DeskSB').checked = false; } // Screen blanking command is not supported, uncheck the screen blanking
                        desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                    });
                } else {
                    desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                }
                // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}


                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{!Mode-NodeWebkit}
                desktop.tlsv1only = amtstack.wsman.comm.tlsv1only;
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                if ((amtsysstate) && (amtsysstate['IPS_ScreenConfigurationService'] != null) && ((amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState'] & 1) != 0)) {
                    amtstack.IPS_ScreenConfigurationService_SetSessionState(Q('id_DeskSB').checked == true ? 1 : 0, 3, function (stack, name, responses, status) {
                        if (status != 200) { Q('id_DeskSB').checked = false; } // Screen blanking command is not supported, uncheck the screen blanking
                        desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                    });
                } else {
                    desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                }
                // ###END###{!Mode-NodeWebkit}
                // ###END###{ComputerSelector}
                // ###BEGIN###{Mode-Firmware}
                desktop.Start();
                // ###END###{Mode-Firmware}
                // ###BEGIN###{Desktop-Multi}
                PullDesktopDisplayInfo();

                if (!urlvars['norefresh']) { desktopPollTimer = setInterval(PullDesktopDisplayInfo, 5000); }

                // ###END###{Desktop-Multi}
            } else {
                desktop.Stop();
                // ###BEGIN###{Desktop-Multi}
                clearInterval(desktopPollTimer);
                desktopPollTimer = null;
                PullDesktopDisplayInfo();
                // ###END###{Desktop-Multi}
                // ###BEGIN###{DesktopInband}
                webRtcDesktopReset();
                // ###END###{DesktopInband}
            }
        }

        // ###BEGIN###{Desktop-Multi}
        function PullDesktopDisplayInfo() {
            if ((amtversion > 7) && (desktop.State > 0)) { amtstack.BatchEnum('', ['*IPS_ScreenSettingData', '*IPS_KVMRedirectionSettingData'], ProcessDesktopDisplayInfo); } else { desktopScreenInfo = null; Q('id_DeskScreenSelector').innerHTML = '' }
        }

        // Update the currently active displays
        function ProcessDesktopDisplayInfo(stack, name, responses, status) {
            if (status != 200) { desktopScreenInfo = null; return; }
            desktopScreenInfo = responses['IPS_ScreenSettingData'].responses.Body;
            desktopScreenInfo.KVMRSD = responses['IPS_KVMRedirectionSettingData'].responses.Body;
            UpdateDesktopDisplayInfo();
        }

        // Update screen icons
        function UpdateDesktopDisplayInfo() {
            var buttons = '', activeScreens = 0;
            for (var i = 0; i < 3; i++) { if (desktopScreenInfo['IsActive'][i] == true) { activeScreens++; buttons += '<input type="button" ' + ((i == desktopScreenInfo.KVMRSD['DefaultScreen'])?'style="background-color:DodgerBlue"':'') + ' value="' + (i + 1) + '" title="Switch to screen ' + (i + 1) + '" onkeypress="return false" onkeydown="return false" onclick="desktopSwitchScreen(' + i + ')">&nbsp;'; } }
            if (activeScreens > 1) { Q('id_DeskScreenSelector').innerHTML = buttons + '&nbsp;'; } else { Q('id_DeskScreenSelector').innerHTML = ''; }
        }

        // Request switch to a different desktop
        function desktopSwitchScreen(x) {
            var k = Clone(desktopScreenInfo.KVMRSD); k['DefaultScreen'] = x; amtstack.Put('IPS_KVMRedirectionSettingData', k, desktopSwitchScreenEx);
        }

        // Response to request for a different desktop
        function desktopSwitchScreenEx(stack, name, responses, status) {
            if (status == 200) { desktopScreenInfo.KVMRSD = responses.Body; UpdateDesktopDisplayInfo(); }
        }
        // ###END###{Desktop-Multi}

        function onDesktopStateChange(desktop, state) {
            var reconnect = false;
            //console.log("onDesktopStateChange: " + state);
            idx_connectbutton1.value = (state == 0) ? "Collegare" : "Disconnect";
            var input = ((state == 3) && !urlvars['kvmviewonly']);
            QE('id_DeskCAD', input);
            QE('deskkeys', input);
            QE('DeskWD', input);
            // ###BEGIN###{DesktopType}
            QE('id_DeskType', input);
            // ###END###{DesktopType}
            // ###BEGIN###{DesktopClipboard}
            QE('id_DeskKvmClipButton', state == 3);
            // ###END###{DesktopClipboard}
            switch (state) {
                case 0:
                    // ###BEGIN###{DesktopRecorder}
                    if (desktop.m.recordedData != null) { deskRecordSession(); }
                    // ###END###{DesktopRecorder}
                    // desktop.m.ResetScreen();
                    // ###BEGIN###{DesktopInband}
                    webRtcDesktopReset();
                    // ###END###{DesktopInband}
                    // ###BEGIN###{Mode-MeshCentral2}
                    QV('deskRecordIcon', false);
                    // ###END###{Mode-MeshCentral2}
                    if (desktop.disconnectCode == 2) { // BUSY
                        messagebox("Desktop remoto", "The remote device is busy, a session may already be open.");
                    } else if (desktop.disconnectCode == 3) { // UNSUPPORTED
                        messagebox("Desktop remoto", "The device indicated that this type of connection of not supported.");
                    } else if (desktop.disconnectCode == 50000) { // KVM-Disconnect
                        messagebox("Desktop remoto", "KVM disconnection, this may indicate that Intel AMT is unable to capture the display (Try RLE8 encoding), or unsupported GPU.");
                    } else if (desktop.disconnectCode == 50001) { // Intel AMT disconnect, try to connect again if connection was more than 5 seconds long.
                        reconnect = (desktop.connectTime != null) && ((desktop.connectTime + 5000) < Date.now());
                        //console.log(desktop.disconnectCode, reconnect);
                    } else if (desktop.disconnectCode == 50002) { // KVM-BufferOverflow
                        messagebox("Desktop remoto", "KVM disconnection that may be due to the display size and resolution being too large for the Intel AMT KVM buffer. Try RLE8 encoding or reducing the display resolution.");
                    }
                    break;
                case 3:
                    // ###BEGIN###{DesktopInband}
                    if (amtversion >= 12) { desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } // If this is Intel AMT 12 or higher, send the soft-KVM presence indicator.
                    // ###END###{DesktopInband}
                    // ###BEGIN###{Mode-MeshCentral2}
                    if (desktop.serverIsRecording == true) { QV('deskRecordIcon', true); }
                    // ###END###{Mode-MeshCentral2}
                    break;
            }
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
            center();
            updateDesktopState();
            if (reconnect) { setTimeout(connectDesktop, 200); }
        }

        // Update remote desktop status
        function updateDesktopState() {
            // ###BEGIN###{DesktopInband}
            var x = '';
            if (desktop.State == 3) {
                if ((webRtcDesktop) && (webRtcDesktop.webRtcActive == true)) {
                    x = ", Soft-KVM";
                } else {
                    if (desktop.m && desktop.m.kvmExt) {
                        if (desktop.m.kvmExt.decimationState == 1) { x += ", Downscaled" }
                        if (desktop.m.kvmExt.compression == 1) { x += ", Compressed" }
                    }
                }
            }
            Q('id_deskstatus').textContent = StatusStrs[desktop.State] + x;
            // ###END###{DesktopInband}
            // ###BEGIN###{!DesktopInband}
            Q('id_deskstatus').textContent = StatusStrs[desktop.State];
            // ###END###{!DesktopInband}
        }

        function showDesktopSettings() {
            if (xxdialogMode) return;
            applyDesktopSettings();
            setDialogMode(7, "Impostazioni desktop remoto", 3, showDesktopSettingsChanged);
        }

        function showDesktopSettingsChanged() {
            desktopsettings.encflags = parseInt(idx_d7desktopmode.value);
            // ###BEGIN###{DesktopFocus}
            desktopsettings.showfocus = d7showfocus.checked;
            if ((amtversion > 15) && (amtsysstate['IPS_KVMRedirectionSettingData'].response['InitialDecimationModeForLowRes'] > 0)) { desktopsettings.decimationMode = parseInt(d7decimation.value); }
            // ###END###{DesktopFocus}
            desktopsettings.showmouse = d7showcursor.checked;
            desktopsettings.showcad = d7showcad.checked;
            desktopsettings.limitFrameRate = d7limitFrameRate.checked;
            desktopsettings.noMouseRotate = d7noMouseRotate.checked;
            desktopsettings.reverseMouseWheel = d7kvmrmw.checked;
            // ###BEGIN###{DesktopInband}
            desktopsettings.quality = d7bitmapquality.value;
            desktopsettings.scaling = d7bitmapscaling.value;
            // ###END###{DesktopInband}
            try { localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings)); } catch (ex) { }
            applyDesktopSettings();
            // ###BEGIN###{DesktopFocus}
            if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; idx_deskFocusBtn.value = "All Focus"; }
            // ###END###{DesktopFocus}
            desktop.m.frameRateDelay = (desktopsettings.limitFrameRate == true)?200:0;
            if (desktop.State != 0) { desktop.disconnectCode = 0; desktop.Stop(); setTimeout(connectDesktop, 800); }
        }

        function applyDesktopSettings() {
            // ###BEGIN###{DesktopFocus}
            d7showfocus.checked = desktopsettings.showfocus;
            // ###END###{DesktopFocus}
            d7decimation.value = desktopsettings.decimationMode;
            d7showcursor.checked = desktopsettings.showmouse;
            d7showcad.checked = desktopsettings.showcad;
            d7limitFrameRate.checked = desktopsettings.limitFrameRate;
            d7noMouseRotate.checked = desktopsettings.noMouseRotate;
            d7kvmrmw.checked = desktopsettings.reverseMouseWheel;
            // ###BEGIN###{DesktopInband}
            if (desktopsettings.quality) { d7bitmapquality.value = desktopsettings.quality; }
            if (desktopsettings.scaling) { d7bitmapscaling.value = desktopsettings.scaling; }
            QV('d7softkvmsettings', amtversion >= 12);
            // ###END###{DesktopInband}
            var encflags = desktopsettings.encflags; // Flags: 1 = RLE, 2 = 16bit, 4 = Gray, 8 = ZLib, 16 = 4bit Color

            var x = '';
            if ((amtversion > 15) && (amtsysstate != null) && (amtsysstate['IPS_KVMRedirectionSettingData'] != null) && (amtsysstate['IPS_KVMRedirectionSettingData'].response)) {
                if (!amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported']) { encflags = encflags & 11; } // Remove grayscale and lowcolor
                if (!amtsysstate['IPS_KVMRedirectionSettingData'].response['ZlibControlSupported']) { encflags = encflags & 23; } // Remove zlib
                if (amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported']) {
                    x += '<option id="d7exm1" value=21>' + "RLE4G, 16 Grays" + '</option>';
                    x += '<option id="d7exm2" value=5>' + "RLE8G, 256 Grays" + '</option>';
                }
                x += '<option value=1>' + "RLE8, 256 Colors" + '</option>';
                x += '<option value=3>' + "RLE16, 64k Colors" + '</option>';
                if (amtsysstate['IPS_KVMRedirectionSettingData'].response['ZlibControlSupported']) {
                    if (amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported']) {
                        x += '<option id="d7exm3" value=29>' + "ZRLE4G, Compressed Gray" + '</option>';
                        x += '<option id="d7exm4" value=13>' + "ZRLE8G, Compressed Gray" + '</option>';
                    }
                    x += '<option id="d7exm5" value=9>' + "ZRLE8, Compressed Color" + '</option>';
                    x += '<option id="d7exm6" value=11>' + "ZRLE16, Compressed Color" + '</option>';
                }
                QV('d7decimationspan', amtsysstate['IPS_KVMRedirectionSettingData'].response['InitialDecimationModeForLowRes'] > 0);
            } else {
                encflags = encflags & 3; // Remove gray & zlib flags (4 and 8), keep 1 & 2
                x += '<option value=1>' + "RLE8, 256 Colors" + '</option>';
                x += '<option value=3>' + "RLE16, 64k Colors" + '</option>';
                QV('d7decimationspan', false);
            }
            x += '<option value=0>' + "RAW8, 256 Colors" + '</option>';
            x += '<option value=2>' + "RAW16, 16k Colors" + '</option>';
            QH('idx_d7desktopmode', x);
            idx_d7desktopmode.value = encflags;
            // ###BEGIN###{DesktopFocus}
            QV('idx_deskFocusBtn', desktopsettings.showfocus);
            // ###END###{DesktopFocus}
            QV('id_DeskCAD', desktopsettings.showcad);
        }

        var fullscreen = false;
        var fullscreenonly = false;
        function deskToggleFull(kvmonly) {
            if (xxdialogMode) return;
            if (fullscreenonly == true) {
                // We are in full screen only mode
                console.log('deskToggleFull1', fullscreenonly, urlvars['kvmonly']);
                fullscreenonly = false;
                if (urlvars['kvmonly'] == 1) {
                    //console.log('deskToggleFull2');
                    // It was initiated by a command line switch, exit now.
                    // ###BEGIN###{Mode-NodeWebkit}
                    require('nw.gui').Window.get().close();
                    // ###END###{Mode-NodeWebkit}
                } else {
                    // It was initiated by a menu selection, disconnect now.
                    disconnect();
                }
                return;
            }
            fullscreenonly = kvmonly;
            fullscreen = !fullscreen;
            // ###BEGIN###{!Look-MeshCentral}
            QV('id_topheader', !fullscreen);
            // ###END###{!Look-MeshCentral}
            QV('id_leftbar', !fullscreen);
            QV('id_rdheader', !fullscreen);
            QV('idx_deskFullBtn', !fullscreen);
            QV('idx_deskFullBtn2', fullscreen);
            if (fullscreen) {
                // ###BEGIN###{!Look-MeshCentral}
                QS('id_mainarea').top = 0;
                // ###END###{!Look-MeshCentral}
                QS('id_mainarea').left = 0;
                QS('id_mainarea_pad').padding = 0;
            } else {
                // ###BEGIN###{!Look-MeshCentral}
                // ###BEGIN###{!Look-ISDU}
                QS('id_mainarea').top = '69px';
                // ###END###{!Look-ISDU}
                // ###BEGIN###{Look-ISDU}
                QS('id_mainarea').top = '94px';
                // ###END###{Look-ISDU}
                // ###END###{!Look-MeshCentral}
                QS('id_mainarea').left = '156px';
                QS('id_mainarea_pad').padding = '8px';
            }
            center();
        }

        // ###BEGIN###{DesktopFocus}
        function deskToggleFocus() {
            desktop.m.focusmode = (desktop.m.focusmode + 64) % 192;
            Q('idx_deskFocusBtn').value = ["All Focus", "Focus ridotto", "Grande attenzione"][desktop.m.focusmode / 64];
        }
        // ###END###{DesktopFocus}

        // ###BEGIN###{DesktopType}
        // Remote desktop typing
        function deskShowTypeDialog() {
            if (xxdialogMode || desktop.State != 3) return;
            Q('id_DeskType').blur();
            var x = '<div>' + "Immettere il testo e fare clic su OK per digitarlo in remoto utilizzando una tastiera inglese statunitense. Assicurarsi di posizionare il cursore remoto nella posizione corretta prima di procedere." + '<div>';
            x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
            setDialogMode(11, "Voce tastiera remota", 3, showDeskTypeEx, x);
            Q('d2typeText').focus();
        }

        var AmtDeskTypeTimer = null;
        var AmtDeskTypeContent = null;
        var DeskTypeTranslate = { 39: 222, 42: 106, 43: 107, 44: 188, 45: 189, 46: 190, 47: 191, 59: 186, 61: 187, 91: 219, 92: 220, 93: 221, 96: 192, 191: 111 };
        var DeskTypeShiftTranslate = { 33: 49, 34: 222, 35: 51, 36: 52, 37: 53, 38: 55, 40: 57, 41: 48, 58: 186, 60: 188, 62: 190, 63: 191, 64: 50, 94: 54, 95: 189, 106: 56, 107: 187, 123: 219, 124: 220, 125: 221, 126: 192 };
        function showDeskTypeEx() {
            var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
            //if (desktop.contype == 2) {
                // Intel AMT
                for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
                AmtDeskTypeContent = x;
                AmtDeskTypeTimer = setInterval(function () {
                    var key = AmtDeskTypeContent.shift();
                    if (desktop) { desktop.m.sendkey(key[0], key[1]); }
                    if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
                }, 10);
             /*
            } else {
                // MeshAgent
                for (var i in txt) {
                    var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
                    if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
                        if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
                        if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
                    } else if ((a >= 48) && (a <= 57)) {
                        if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
                    } else if (DeskTypeTranslate[a]) {
                        if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
                        b = DeskTypeTranslate[a];
                    } else if (DeskTypeShiftTranslate[a]) {
                        if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
                        b = DeskTypeShiftTranslate[a];
                    }
                    x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
                }
                if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
                desktop.m.SendKeyMsgKC(x);
            }
            */
        }
        // ###END###{DesktopType}

        // Send CTRL-ALT-DEL
        function sendCAD() { if (!Q('id_DeskVO').checked) { desktop.m.sendcad(); } }

        // Special keys
        var deskkeysset = {
            0: [[0xffe7, 1], [0xffe7, 0]], // Win
            1: [[0xffe7, 1], [0xff54, 1], [0xff54, 0], [0xffe7, 0]], // Win+Down
            2: [[0xffe7, 1], [0xff52, 1], [0xff52, 0], [0xffe7, 0]], // Win+Up
            3: [[0xffe7, 1], [0x6c, 1], [0x6c, 0], [0xffe7, 0]], // Win+L
            4: [[0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0]], // Win+M
            5: [[0xffe1, 1], [0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0], [0xffe1, 0]], // Shift+Win+M
            6: [[0xffbe, 1], [0xffbe, 0]], // F1
            7: [[0xffbf, 1], [0xffbf, 0]], // F2
            8: [[0xffc0, 1], [0xffc0, 0]], // F3
            9: [[0xffc1, 1], [0xffc1, 0]], // F4
            10: [[0xffc2, 1], [0xffc2, 0]], // F5
            11: [[0xffc3, 1], [0xffc3, 0]], // F6
            12: [[0xffc4, 1], [0xffc4, 0]], // F7
            13: [[0xffc5, 1], [0xffc5, 0]], // F8
            14: [[0xffc6, 1], [0xffc6, 0]], // F9
            15: [[0xffc7, 1], [0xffc7, 0]], // F10
            16: [[0xffc8, 1], [0xffc8, 0]], // F11
            17: [[0xffc9, 1], [0xffc9, 0]], // F12
            //18: [[0xffe1, 1], [0xffe9, 1], [65, 1], [65, 0], [0xffe9, 0], [0xffe1, 0]]   // Left-Shift + Left-Alt + Print Screen
            19: [[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]],  // Alt-Tab
            20: [[0xffe7, 1], [0x72, 1], [0x72, 0], [0xffe7, 0]], // WIN+R
            21: [[0xffe9, 1], [0xffc1, 1], [0xffc1, 0], [0xffe9, 0]], // Alt-F4
            22: [[0xffe3, 1], [0x77, 1], [0x77, 0], [0xffe3, 0]], // Ctrl-W
            23: [[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]], // WIN+Left
            24: [[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]], // Win+Right
            25: [[0xff0d, 1], [0xff0d, 0]] // Enter
        }

        // Send special keys to the remote side.
        function deskSendKeys() {
            if (Q('id_DeskVO').checked) return;
            var ks = Q('deskkeys').value;
            if (ks != null && deskkeysset[ks] != null && desktop.State != 0) {
                for (var i = 0; i < deskkeysset[ks].length; i++) {
                    desktop.m.sendkey(deskkeysset[ks][i][0], deskkeysset[ks][i][1]);
                }
            }
        }

        // ###BEGIN###{DesktopClipboard}
        // Toggle desktop session recording
        function deskClipboard() {
            if (xxdialogMode || (desktop == null) || (desktop.State != 3)) return;
            var x = '';
            x += "Immettere il testo da inviare agli Appunti Intel&reg; AMT." + '<br />';
            x += '<select id=kvmClipEncoding style=width:100%;margin-top:8px><option value=0>' + "Text Encoding" + '<option value=1>' + "Hex Encoding" + '</select>';
            x += '<textarea id=kvmClipText style=width:100%;height:120px;resize:none;margin-top:8px />';
            setDialogMode(11, "appunti", 3, deskClipboardEx, x);
            focusTextBox('kvmClipText');
            if (xxKvmClipEnc != null) { Q('kvmClipEncoding').value = xxKvmClipEnc; }
            if (xxKvmClipVal != null) { Q('kvmClipText').value = xxKvmClipVal; }
        }

        function deskClipboardEx() {
            xxKvmClipEnc = Q('kvmClipEncoding').value;
            xxKvmClipVal = Q('kvmClipText').value;
            if (Q('kvmClipEncoding').value == 0) {
                desktop.m.sendClipboardData(Q('kvmClipText').value.split('\\0').join('\0')); // Text encoded input
            } else {
                desktop.m.sendClipboardData(hex2rstr(Q('kvmClipText').value)); // Hex encoded input
            }
        }
        // ###END###{DesktopClipboard}

        // ###BEGIN###{FileSaver}
        // ###BEGIN###{DesktopRecorder}
        // Toggle desktop session recording
        function deskRecordSession() {
            if ((desktop == null) || (urlvars && urlvars['norecord'])) return;
            if (desktop.m.recordedData == null) {
                // Start recording
                if ((desktop.State === 3) && (desktop.m.StartRecording())) { Q('DeskRecordButton').classList.remove('videoIcon'); Q('DeskRecordButton').classList.add('videoIconRed'); }
            } else {
                // Stop recording
                Q('DeskRecordButton').classList.remove('videoIconRed');
                Q('DeskRecordButton').classList.add('videoIcon');
                var d = new Date(), n = 'AmtDesktopSesion-' + currentcomputer['name'] + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
                saveAs(data2blob(desktop.m.StopRecording().join('')), n + '.mcrec');
            }
        }
        // ###END###{DesktopRecorder}
        // ###END###{FileSaver}

        // ###BEGIN###{FileSaver}
        // Save the desktop image to file
        function deskSaveImage() {
            if (xxdialogMode || (desktop.State != 3) || (urlvars && urlvars['norecord'])) return;
            var n = 'Desktop', d = new Date();
            if (amtsysstate) { n += '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
            n += '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
            // ###BEGIN###{!Mode-NodeWebkit}
            Q('Desk')['toBlob']( function (blob) { saveAs(blob, n + '.jpg'); } );
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var b64image = document.getElementById('Desk').toDataURL('image/png').split(',')[1];
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', n + '.png');
            chooser.addEventListener('change', function () { console.log('cc'); require('fs').writeFile(this.value, b64image, 'base64', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        // Send special keys
        //function sendSpecialKey() { var k = Q('specialkeylist').value; desktop.m.sendkey(k, 1); desktop.m.sendkey(k, 0); }

        // ###BEGIN###{!DesktopInband}
        function dmousedown(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mousedown(e); }
        function dmouseup(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mouseup(e); }
        function dmousemove(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mousemove(e); }
        function dmousewheel(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mousewheel(e); }
        // ###END###{!DesktopInband}
        // ###BEGIN###{DesktopInband}
        function dmousedown(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } }
        function dmouseup(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } } }
        function dmousemove(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
        function dmousewheel(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousewheel(e); } } }
        // ###END###{DesktopInband}

        function drotate(x) {
            if (xxdialogMode) return;
            var r = desktop.m.rotation + x;
            desktop.m.setRotation(r);
            // ###BEGIN###{DesktopInband}
            if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null) && (webRtcDesktop.softdesktop.m != null)) {
                webRtcDesktop.softdesktop.m.setRotation(r); }
            // ###END###{DesktopInband}
            center();
        }

        // ###BEGIN###{DesktopInbandFiles}
        
        // 
        // Remote Files
        //

        var p24files = null;
        var p24filetree = null;
        var p24targetpath = null;
        var p24filetreelocation = [];

        function onFilesControlData(data) {
            if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p24gotDownloadBinaryData(data); return; }
            data = JSON.parse(data);
            if (data.action == 'download') { p24gotDownloadCommand(data); return; }
            if (data.action == 'upload') { p24gotUploadData(data); return; }
            if (data.action == 'pong') { return; }
            data.path = data.path.replace(/\//g, '\\');
            if ((p24filetree != null) && (data.path == p24filetree.path)) {
                // This is an update to the same folder
                var checkedNames = p24getCheckedNames();
                p24filetree = data;
                p24updateFiles(checkedNames);
            } else {
                // Make both paths use the same seperator not start with /
                var x1 = data.path.split('/').join('\\');
                var x2 = p24targetpath.split('/').join('\\');
                while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
                while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
                if ((x1 == x2) || ((data.path == '\\') && (p24targetpath == ''))) {
                    // This is a different folder
                    p24filetree = data;
                    p24updateFiles();
                }
            }
        }

        function p24getCheckedNames() {
            // Save all existing checked boxes
            var checkedNames = [], checkboxes = document.getElementsByName('fd');
            for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedNames.push(p24filetree.dir[checkboxes[i].value].n) }; }
            return checkedNames;
        }

        //var p24oldlinkpath = null;
        function p24updateFiles(checkedNames) {
            var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p24folderup(0)>' + "Radice" + '</a>', fullPath = 'Root';

            // Work on parsing the file path
            var x = p24filetree.path.split('\\');
            p24filetreelocation = [];
            for (var i in x) { if (x[i] != '') { p24filetreelocation.push(x[i]); } } // Remove empty spaces
            for (var i in p24filetreelocation) { displayPath += ' / <a style=cursor:pointer onclick=p24folderup(' + (parseInt(i) + 1) + ')>' + p24filetreelocation[i] + '</a>' } // Setup the path we display
            var newlinkpath = p24filetreelocation.join('/');

            // Sort the files
            var filetreexx = p24sort_files(p24filetree.dir);

            // Display all files and folders at this location
            for (var i in filetreexx) {
                // Figure out the name and shortname
                var f = filetreexx[i], name = f.n, shortname;
                shortname = name;
                if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + "..." + '</span>'; } else { shortname = EscapeHtml(name); }
                name = EscapeHtml(name);

                // Figure out the date
                var fdatestr = '';
                if (f.d != null) { var fdate = new Date(f.d), fdatestr = (fdate.getMonth() + 1) + '/' + (fdate.getDate()) + '/' + fdate.getFullYear() + ' ' + fdate.toLocaleTimeString() + '&nbsp;'; }

                // Figure out the size
                var fsize = '';
                if (f.s != null) { fsize = getFileSizeStr(f.s); }

                var h = '';
                if (f.t < 3) {
                    var right = '', title = '';
                    h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p24setActions() value="' + f.nx + '">&nbsp;<span style=float:right title=\"' + title + '\">' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p24folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
                } else {
                    var link = shortname;
                    if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\'p24downloadfile("' + encodeURIComponent(newlinkpath + '/' + name) + '","' + encodeURIComponent(name) + '",' + f.s + ')\'>' + shortname + '</a>'; }
                    h = '<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p24setActions() value="' + f.nx + '">&nbsp;<span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
                }

                if (f.t < 3) { html1 += h; } else { html2 += h; }
            }

            // Display the files and path
            QH('p24files', html1 + html2);
            QH('p24currentpath', displayPath);
            QE('p24FolderUp', p24filetreelocation.length != 0);

            // Re-check all boxes if needed using names
            if (checkedNames != null) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkedNames.indexOf(p24filetree.dir[checkboxes[i].value].n) >= 0) { checkboxes[i].checked = true; } } }

            // Update the actions buttons
            p24setActions();
        }

        function p24folderset(x) {
            p24targetpath = joinPaths(p24filetree.path, p24filetree.dir[x].n).split('\\').join('/');
            p24files.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: p24targetpath }));
        }

        function p24folderup(x) {
            if (x == null) { p24filetreelocation.pop(); } else { while (p24filetreelocation.length > x) { p24filetreelocation.pop(); } }
            p24targetpath = p24filetreelocation.join('/');
            p24files.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: p24targetpath }));
        }

        var p24sortorder;
        function p24sort_filename(a, b) { if (a.ln > b.ln) return (1 * p24sortorder); if (a.ln < b.ln) return (-1 * p24sortorder); return 0; }
        function p24sort_timestamp(a, b) { if (a.d > b.d) return (1 * p24sortorder); if (a.d < b.d) return (-1 * p24sortorder); return 0; }
        function p24sort_bysize(a, b) { if (a.s == b.s) return p24sort_filename(a, b); return (((a.s - b.s)) * p24sortorder); }

        function p24sort_files(files) {
            var r = [], sortselection = Q('p24sortdropdown').value;
            for (var i in files) { files[i].nx = i; if (files[i].s == null) { files[i].s = 0; } if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
            p24sortorder = 1;
            if (sortselection > 3) { p24sortorder = -1; sortselection -= 3; }
            if (sortselection == 1) { r.sort(p24sort_filename); }
            else if (sortselection == 2) { r.sort(p24sort_bysize); }
            else if (sortselection == 3) { r.sort(p24sort_timestamp); }
            return r;
        }

        function p24setActions() {
            if (p24filetree == null) {
                QE('p24DeleteFileButton', false);
                QE('p24NewFolderButton', false);
                QE('p24UploadButton', false);
                QE('p24RenameFileButton', false);
                QE('p24SelectAllButton', false);
                Q('p24SelectAllButton').value = "Seleziona tutto";
                QE('p24RefreshButton', false);
                QE('p24CutButton', false);
                QE('p24CopyButton', false);
                QE('p24PasteButton', false);
            } else {
                var cc = p24getFileSelCount(), tc = p24getFileCount(), sfc = p24getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
                var winAgent = (webRtcDesktop.platform == 'win32');
                QE('p24DeleteFileButton', (cc > 0) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24NewFolderButton', ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24UploadButton', ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24RenameFileButton', (cc == 1) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24SelectAllButton', tc > 0);
                Q('p24SelectAllButton').value = (cc > 0 ? "Non selezionare niente" : "Seleziona tutto");
                QE('p24RefreshButton', true);
                QE('p24CutButton', (cc > 0) && (cc == sfc) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24CopyButton', (cc > 0) && (cc == sfc) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24PasteButton', ((p24filetreelocation.length > 0) || (winAgent == false)) && ((p24clipboard != null) && (p24clipboard.length > 0)));
            }
        }

        function p24getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
        function p24getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
        function p24selectallfile() { var nv = (p24getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p24setActions(); }
        function p24createfolder() { setDialogMode(11, "Nuova cartella", 3, p24createfolderEx, '<input type=text id=p24renameinput maxlength=64 onkeyup=p24fileNameCheck(event) style=width:100% />'); focusTextBox('p24renameinput'); p24fileNameCheck(); }
        function p24createfolderEx() { p24files.sendCtrlMsg(JSON.stringify({ action: 'mkdir', reqid: 1, path: p24filetreelocation.join('/') + '/' + Q('p24renameinput').value })); p24folderup(999); }
        function p24deletefile() { var cc = p24getFileSelCount(); setDialogMode(11, "Elimina", 3, p24deletefileEx, (cc > 1) ? ('Delete ' + cc + ' selected items?') : ('Delete selected item?')); }
        function p24deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(p24filetree.dir[checkboxes[i].value].n); } } p24files.sendCtrlMsg(JSON.stringify({ action: 'rm', reqid: 1, path: p24filetreelocation.join('/'), delfiles: delfiles })); p24folderup(999); }
        function p24renamefile() { var renamefile, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = p24filetree.dir[checkboxes[i].value].n; } } setDialogMode(11, "Rinominare", 3, p24renamefileEx, '<input type=text id=p24renameinput maxlength=64 onkeyup=p24fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'rename', path: p24filetreelocation.join('/'), oldname: renamefile }); focusTextBox('p24renameinput'); p24fileNameCheck(); }
        function p24renamefileEx(b, t) { t.newname = Q('p24renameinput').value; p24files.sendCtrlMsg(JSON.stringify(t)); p24folderup(999); }
        function p24fileNameCheck(e) { var x = isFilenameValid(Q('p24renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 24)) { dialogclose(1); } }
        function p24uploadFile() { setDialogMode(11, "Caricare un file", 3, p24uploadFileEx, '<input type=file name=files id=p24uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p24uploadinput\')" />'); updateUploadDialogOk('p24uploadinput'); }
        function p24uploadFileEx() { p24doUploadFiles(Q('p24uploadinput').files); }
        function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }

        var p24clipboard = null, p24clipboardFolder = null, p24clipboardCut = 0;
        function p24copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p24clipboard = []; p24clipboardCut = cut, p24clipboardFolder = p24targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == "3")) { p24clipboard.push(p24filetree.dir[checkboxes[i].value].n); } } p24updateClipview(); }
        function p24pasteFile() { var x = ''; if ((p24clipboard != null) && (p24clipboard.length > 0)) { x = 'Confim ' + (p24clipboardCut == 0 ? 'copy' : 'move') + ' of ' + p24clipboard.length + ' entrie' + ((p24clipboard.length > 1) ? 's' : '') + ' to this location?' } setDialogMode(11, "Incolla", 3, p24pasteFileEx, x); }
        function p24pasteFileEx() { p24files.sendCtrlMsg(JSON.stringify({ action: (p24clipboardCut == 0 ? 'copy' : 'move'), reqid: 1, scpath: p24clipboardFolder, dspath: p24targetpath, names: p24clipboard })); p24folderup(999); if (p24clipboardCut == 1) { p24clipboard = null, p24clipboardFolder = null, p24clipboardCut = 0; p24updateClipview(); } }
        function p24updateClipview() { var x = ''; if ((p24clipboard != null) && (p24clipboard.length > 0)) { x = 'Holding ' + p24clipboard.length + ' entrie' + ((p24clipboard.length > 1) ? 's' : '') + ' for ' + (p24clipboardCut == 0 ? 'copy' : 'move') + ', <a onclick=p24clearClip() style=cursor:pointer>Clear</a>.' } QH('p24bottomstatus', x); p24setActions(); }
        function p24clearClip() { p24clipboard = null; p24clipboardFolder = null; p24clipboardCut = 0; p24updateClipview(); }

        function p24fileDragDrop(e) {
            haltEvent(e);
            QV('p24bigfail', false);
            QV('p24bigok', false);
            if (e.dataTransfer == null || e.dataTransfer.files.length == 0 || p24filetree == null) return;
            if ((p24filetreelocation.length == 0) && (webRtcDesktop.platform == 'win32')) return // If this is Windows, do not accept files in the root folder
            p24doUploadFiles(e.dataTransfer.files);
        }

        var p24dragtimer = null;
        function p24fileDragOver(e) {
            haltEvent(e);
            if (p24dragtimer != null) { clearTimeout(p24dragtimer); p24dragtimer = null; }
            var ac = (p24filetree != null); // Set to true if we can accept the file
            if ((p24filetreelocation.length == 0) && (webRtcDesktop.platform == 'win32')) { ac = false; } // If this is Windows, do not accept files in the root folder
            QV('p24bigok', ac);
            QV('p24bigfail', !ac);
        }

        function p24fileDragLeave(e) {
            haltEvent(e);
            if (e.target.id != "p24filetable") {
                QV('p24bigfail', false);
                QV('p24bigok', false);
            } else {
                p24dragtimer = setTimeout(function () { QV('p24bigfail', false); QV('p24bigok', false); p24dragtimer = null; }, 200);
            }
        }

        function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format("{0} byte", size); }
        function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
        var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
        function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }


        //
        // FILES DOWNLOAD
        //

        var downloadFile; // Global state for file download

        // Called by the html page to start a download, arguments are: path, file name and file size.
        function p24downloadfile(x, y, z) {
            if (xxdialogMode || downloadFile || !p24files) return;
            downloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random() }
            //console.log('p24downloadFileCancel', downloadFile);
            p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path }));
            setDialogMode(11, "Download file", 10, p24downloadFileCancel, '<div>' + downloadFile.file + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
        }

        // Called by the html page to cancel the download
        function p24downloadFileCancel() { if (downloadFile != null) { setDialogMode(0); if (p24files != null) { p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'cancel', id: downloadFile.id })); } downloadFile = null; } }

        // Called by the transport when download control command is received
        function p24gotDownloadCommand(cmd) {
            //console.log('p24gotDownloadCommand', cmd);
            if ((downloadFile == null) || (cmd.id != downloadFile.id)) return;
            if (cmd.sub == 'start') { downloadFile.state = 1; p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'startack', id: downloadFile.id })); }
            else if (cmd.sub == 'cancel') { downloadFile = null; setDialogMode(0); }
        }

        // Called by the transport when binary data is received
        function p24gotDownloadBinaryData(data) {
            if (!downloadFile || downloadFile.state == 0) return;
            try { data = atob(data); } catch (ex) { return; }
            if ((data == null) || (data.length < 4)) return;
            if (data.length > 4) {
                downloadFile.tsize += data.length - 4; // Add to the total bytes received
                downloadFile.data += data.substring(4); // Append the data, decode Base64
                Q('d2progressBar').value = downloadFile.tsize; // Change the progress bar
            }
            if ((ReadInt(data, 0) & 1) != 0) { // Check end flag
                saveAs(data2blob(downloadFile.data), downloadFile.file); downloadFile = null; setDialogMode(0); // Save the file
            } else {
                p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'ack', id: downloadFile.id })); // Send the ACK
            }
        }

        //
        // FILES UPLOAD
        //

        var uploadFile;

        function p24doUploadFiles(files) {
            if (xxdialogMode) return;
            uploadFile = { xpath: p24filetreelocation.join('/'), xfiles: files, xfilePtr: -1 };
            setDialogMode(11, "Caricare un file", 10, p24uploadFileCancel, '<div id=p24dfileName>' + "Impostare..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />', 99);
            p24uploadNextFile();
        }

        // Push the next file
        function p24uploadNextFile() {
            uploadFile.xfilePtr++;
            if (uploadFile.xfiles.length > uploadFile.xfilePtr) {
                uploadFile.xptr = 0;
                var file = uploadFile.xfiles[uploadFile.xfilePtr];
                QH('p24dfileName', file.name);
                Q('d2progressBar').max = file.size;
                Q('d2progressBar').value = 0;
                uploadFile.xreader = new FileReader();
                uploadFile.xreader.onload = function () {
                    uploadFile.xdata = uploadFile.xreader.result;
                    p24files.sendCtrlMsg(JSON.stringify({ action: 'upload', sub: 'start', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
                };
                uploadFile.xreader.onerror = function () { p24uploadNextFile(); }
                uploadFile.xreader.readAsArrayBuffer(file);
            } else {
                p24uploadFileCancel();
                p24folderup(9999); // Refresh the file view
            }
        }

        // Used to cancel the entire transfer, close the upload dialog box
        function p24uploadFileCancel(button, tag) {
            if (uploadFile != null) {
                uploadFile = null;
                setDialogMode(0);
                if ((tag == 99) && (p24files != null)) { p24files.sendCtrlMsg(JSON.stringify({ action: 'upload', sub: 'cancel' })); }
            }
        }

        // Receive upload ack from the mesh agent, use this to keep sending more data
        function p24gotUploadData(cmd) {
            if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
            if (cmd.sub == 'start') {
                p24uploadNextPart(false);
                for (var i = 0; i < 8; i++) { p24uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
            } else if (cmd.sub == 'ack') {
                p24uploadNextPart(false);
            } else if (cmd.sub == 'error') {
                p24uploadFileCancel();
            }
        }

        function ab2str(buf) { return String.fromCharCode.apply(null, new Uint8Array(buf)); }

        // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
        function p24uploadNextPart(dataPriming) {
            var data = uploadFile.xdata, start = uploadFile.xptr, end = uploadFile.xptr + 4096;
            if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
            if (start == data.byteLength) {
                p24uploadNextFile();
            } else {
                p24files.sendCtrlMsg(btoa(IntToStr((end != data.byteLength) ? 0x01000000 : 0x01000001) + ab2str(data.slice(start, end))));
                uploadFile.xptr = end;
                Q('d2progressBar').value = end;
            }
        }

        // ###END###{DesktopInbandFiles}
        // ###END###{Desktop}

        //
        // Remote IDER
        //

        // ###BEGIN###{IDER}

        var ider;
        var iderCodeBlock;
        var iderTimer;

        // ###BEGIN###{IDER-IMRSDK}
        function iderStartIMR() {
            // Setup the IDER session (NodeJS with IMRSDK.dll)
            iderStop();
            ider = CreateAmtRemoteIderIMR();
            if (ider == null) return;
            ider.digestRealmMatch = wsstack.comm.digestRealm;
            ider.onStateChanged = onIderStateChange;
            ider.m.onDialogPrompt = onIderDialogPrompt;

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                ider.m.Start(currentcomputer._id, 16992, 'x', 'x', 0, wsstack.comm, meshCentralServer);
            } else {
                // ###END###{MeshServerConnect}
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                ider.m.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], amtstack.wsman.comm.xtlsCertificate, wsstack.comm.xtlsoptions);
                // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}

            QV('IDERDiskMapButton', false); // Hide the disk heat map button since it's not supported.
        }

        function onIderSourceChange() {
            var sel = Q('storagesourceoption').value;
            QV('iderisofile', (sel & 1) == 0);
            QV('iderimgfile', (sel & 2) == 0);
            QV('iderisodrive', (sel & 1) != 0);
            QV('iderimgdrive', (sel & 2) != 0);
        }
        // ###END###{IDER-IMRSDK}

        function iderStart(e) {
            if (xxdialogMode) return;
            // ###BEGIN###{IDER-IMRSDK}
            if ((e.shiftKey != true) && (require('os').platform() == 'win32')) { iderStartIMR(); return; }
            // ###END###{IDER-IMRSDK}

            // Setup the IDER session (WebSocket)
            var x = '<div>' + "Montare le immagini del disco su un computer Intel&reg; AMT - Sperimentale." + '</div><br />';
            x += '<div style=height:26px><input id=floppyImageInput type=file style=float:right;width:250px accept=".img"><div>' + NoBreak("Floppy (.img)") + '</div></div>';
            x += '<div style=height:26px><input id=cdromImageInput type=file style=float:right;width:250px accept=".iso"><div>' + NoBreak("CDROM (.iso)") + '</div></div>';
            x += '<div style=height:26px><select id=iderStartType style=float:right;width:250px><option value=0>' + "Al prossimo avvio" + '<option value=1>' + "Grazioso" + '<option value=2>' + "Immediato" + '</select><div>' + "Inizio sessione" + '</div></div>';
            setDialogMode(11, "Reindirizzamento archiviazione", 3, iderStart2, x);
            var iderurl = null;
            try { iderurl = localStorage.getItem('iderurl'); } catch (ex) { }
            if (iderurl) { Q('storageserverurl').value = iderurl.substring(1, iderurl.length - 1); }
        }

        function iderStart2() {
            // Check the files
            if ((Q('floppyImageInput').files.length != 1) && (Q('cdromImageInput').files.length != 1)) { messagebox("Errore di reindirizzamento della memoria", "È necessario selezionare almeno un file immagine del disco."); return; }
            if ((Q('floppyImageInput').files.length == 1) && ((Q('floppyImageInput').files[0].size % 512) != 0)) { messagebox("Errore di reindirizzamento della memoria", "File .img non valido."); return; }
            if ((Q('cdromImageInput').files.length == 1) && ((Q('cdromImageInput').files[0].size % 2048) != 0)) { messagebox("Errore di reindirizzamento della memoria", "File .iso non valido."); return; }

            // Fetch the files
            var floppy = null, cdrom = null;
            if (Q('floppyImageInput').files.length == 1) { floppy = Q('floppyImageInput').files[0]; }
            if (Q('cdromImageInput').files.length == 1) { cdrom = Q('cdromImageInput').files[0]; }
            if ((floppy != null) || (cdrom != null)) { iderStart3(floppy, cdrom, Q('iderStartType').value); }
        }

        function iderStart3(floppy, cdrom, iderStart) {
            // Setup the IDER session
            iderStop();
            ider = CreateAmtRedirect(CreateAmtRemoteIder());
            ider.onStateChanged = onIderStateChange;
            ider.m.floppy = floppy;
            ider.m.cdrom = cdrom;
            ider.m.iderStart = iderStart;
            // ###BEGIN###{ComputerSelector}
            ider.digestRealmMatch = wsstack.comm.digestRealm;
            // ###END###{ComputerSelector}
            // ###BEGIN###{IDERStats}
            ider.m.sectorStats = iderSectorStats;
            // ###END###{IDERStats}

            // ###BEGIN###{Mode-MeshCentral2}
            ider.tlsv1only = amtstack.wsman.comm.tlsv1only;
            ider.Start(currentMeshNode._id, 16994, '*', '*', 0);
            // ###END###{Mode-MeshCentral2}
            // ###BEGIN###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-Firmware}
            ider.Start();
            // ###END###{Mode-Firmware}
            // ###BEGIN###{!Mode-Firmware}
            ider.tlsv1only = amtstack.wsman.comm.tlsv1only;
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                desktop.Start(currentcomputer._id, 0, 'x', 'x', 0, wsstack.comm, meshCentralServer);
            } else {
            // ###END###{MeshServerConnect}
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                // ###BEGIN###{!Mode-NodeWebkit}
                ider.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                // ###END###{!Mode-NodeWebkit}
                // ###BEGIN###{Mode-NodeWebkit}
                ider.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}
            // ###END###{!Mode-Firmware}
            // ###END###{!Mode-MeshCentral2}

            QV('IDERDiskMapButton', true); // Show the disk heat map button since it is supported.
        }

        function iderStop() {
            // Stop the IDER session
            if (ider) { ider.m.Stop(); ider.onStateChanged = null; ider.m.onDialogPrompt = null; delete ider; }
            if (iderTimer) { clearInterval(iderTimer); delete iderTimer; }
            // ###BEGIN###{IDERStats}
            iderToggleDiskMap(false);
            // ###END###{IDERStats}
        }

        function onIderStateChange(stack, state) {
            QE('idx_IDER1', state != 3);
            QE('idx_IDER2', state != 3);
            // ###BEGIN###{Mode-MeshCentral2}
            QE('idx_SIDER1', state != 3);
            QE('idx_SIDER2', state != 3);
            // ###END###{Mode-MeshCentral2}

            QV('id_iderstatus', state == 3); center();
            if (state == 3) {
                if (!urlvars['norefresh']) { iderTimer = setInterval(onIderTimer, 500); }
                onIderTimer();
            } else {
                if (iderTimer) { clearInterval(iderTimer); delete iderTimer; }
            }
        }

        function onIderTimer() {
            if (ider.m.Update) { ider.m.Update(); }
            if (ider.m.bytesFromAmt == -1) { iderStop(); } else { QH('id_iderstatusstr', '<b>' + (ider.m.server?"server":'') + "Sessione IDE-R </b>, connessa," + ider.m.bytesFromAmt + " in," + ider.m.bytesToAmt + " su."); }
        }

        // ###BEGIN###{IDERStats}
        var heatMapWidth = 600;
        var heatMapDividor = {};
        function iderSectorStats(mode, dev, total, start, len) {
            var canvas = dev ? Q('cdromHeatMapCanvas') : Q('floppyHeatMapCanvas');
            var ctx = canvas.getContext('2d');
            if (mode == 0) {
                heatMapDividor[dev] = 1;
                if (total > 0) { while ((total / heatMapDividor[dev]) > 8000) { heatMapDividor[dev] *= 2; } }
                if (dev) {
                    QV('cdromHeatMap', total)
                    QH('cdromHeatMapText', format("<b> CDROM </b>, i blocchi sono {0} byte.", (2048 * heatMapDividor[dev])));
                } else {
                    QV('floppyHeatMap', total);
                    QH('floppyHeatMapText', format("<b> Floppy </b>, i blocchi sono {0} byte.", (512 * heatMapDividor[dev])));
                }
            }
            var dividor = heatMapDividor[dev];
            total = total / dividor;
            start = start / dividor;
            len = len / dividor;
            var heatMapScale = 6;
            if (mode == 0) {
                canvas.height = ((Math.floor(total / (heatMapWidth / heatMapScale)) + ((total % heatMapWidth) ? 1 : 0)) * heatMapScale);
                ctx.fillStyle = 'rgba(225,250,225,1)';
                ctx.fillRect(0, 0, heatMapWidth, Math.floor(total / (heatMapWidth / heatMapScale)) * heatMapScale);
                if (total % heatMapWidth) { ctx.fillRect(0, Math.floor(total / (heatMapWidth / heatMapScale)) * heatMapScale, (total % (heatMapWidth / heatMapScale)) * heatMapScale, heatMapScale); }
                ctx.fillStyle = 'rgba(0,0,0,0.3)';
            } else {
                for (var i = start; i < start + len; i++) { sectorHeat(ctx, i, heatMapScale, dividor); }
            }
        }

        function sectorHeat(ctx, sector, scale, dividor) {
            ctx.fillRect((sector % (heatMapWidth / scale)) * scale, Math.floor(sector / (heatMapWidth / scale)) * scale, scale, scale);
        }

        function iderToggleDiskMap(x) {
            var visible = (QS('iderHeatmap').display != 'none');
            if (x == null) { x = !visible; }
            if (xxdialogMode) { x = false; }
            QS('iderHeatmap').display = x ? '' : 'none';
        }
        // ###END###{IDERStats}

        function onIderDialogPrompt(sender, args, buttons) {
            if (iderCodeBlock) { document.body.removeChild(iderCodeBlock); delete iderCodeBlock; }
            if (args['js']) { var JS = document.createElement('script'); JS.text = args['js']; iderCodeBlock = document.body.appendChild(JS); }
            setDialogMode(11, "Reindirizzamento archiviazione", buttons ? buttons : 3, onIderDialogPromptOk, args['html']);
        }

        function onIderDialogPromptOk(button) {
            if (button == 1) {
                // ###BEGIN###{!Mode-NodeWebkit}
                if (window['iderServerCall']) { ider.m.dialogPrompt(window['iderServerCall']()); } else { ider.m.dialogPrompt(); }
                // ###END###{!Mode-NodeWebkit}
                // ###BEGIN###{Mode-NodeWebkit}
                ider.m.dialogPrompt(iderUserConsent);
                // ###END###{Mode-NodeWebkit}
            } else {
                iderStop();
            }
        }

        // ###BEGIN###{Mode-NodeWebkit}
        var restartIderFunction;
        function iderUserConsent(func) {
            restartIderFunction = func;
            amtstack.IPS_OptInService_StartOptIn(iderUserConsent2, 0, 1);
        }

        function iderUserConsent2(stack, name, response, status) {
            if (errcheck(status, stack)) return;
            //console.log("powerActionResponseC1(" + name + "," + response + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                messagebox("Errore di consenso dell'utente", response.Body.ReturnValueStr.replace(/_/g, ' '));
            } else {
                d6ConsentText.value = ''; // Reset user consent code to empty
                setDialogMode(6, "Consenso dell'utente", 11, iderUserConsent3);
                checkConsentDisplay();
                consentChanged();
            }
        }

        function iderUserConsent3() {
            //console.log('IPS_OptInService_SendOptInCode()');
            amtstack.IPS_OptInService_SendOptInCode(d6ConsentText.value, iderUserConsent4, 0, 1);
        }

        function iderUserConsent4(stack, name, response, status) {
            if (errcheck(status, stack)) return;
            //console.log("powerActionResponseC2(" + name + "," + response + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                messagebox("Errore di consenso dell'utente", response.Body.ReturnValueStr.replace('_',' '));
            } else {
                restartIderFunction();
            }
        }
        // ###END###{Mode-NodeWebkit}

        // ###BEGIN###{Mode-MeshCentral2}

        // Server-side IDER
        function iderServerStart() {
            if (xxdialogMode) return;

            // Setup the IDER session (NodeJS)
            iderStop();
            ider = CreateAmtRemoteServerIder();
            if (ider == null) return;
            ider.onStateChanged = onIderStateChange;
            ider.m.sectorStats = iderSectorStats;
            ider.m.onDialogPrompt = onIderDialogPrompt;
            ider.tlsv1only = amtstack.wsman.comm.tlsv1only;
            ider.Start(currentMeshNode._id, 16994, '*', '*', 0);
        }

        // ###END###{Mode-MeshCentral2}

        // ###END###{IDER}

        // ###BEGIN###{RemoteAccess}

        //
        // Remote Access
        //

        var xxRemoteAccess = null;
        var xxEnvironementDetection = null;
        var xxCiraServers = null;
        var xxUserInitiatedCira = null;
        var xxUserInitiatedEnabledState = { 32768: "Disabilitato", 32769: "BIOS abilitato", 32770: "Abilitazione SO", 32771: "BIOS e sistema operativo abilitati" };
        var xxRemoteAccessCredentiaLinks = null;
        var xxMPSUserPass = null;
        var xxPolicies = null;

        function PullRemoteAccess() {
            // We only deal with remote access starting with Intel AMT 6 and beyond
            // ###BEGIN###{Certificates}
            var requests = ['*AMT_EnvironmentDetectionSettingData', 'AMT_ManagementPresenceRemoteSAP', 'AMT_RemoteAccessCredentialContext', 'AMT_RemoteAccessPolicyAppliesToMPS', 'AMT_RemoteAccessPolicyRule', '*AMT_UserInitiatedConnectionService', 'AMT_MPSUsernamePassword'];
            // ###END###{Certificates}
            // ###BEGIN###{!Certificates}
            var requests = ['*AMT_EnvironmentDetectionSettingData', 'AMT_ManagementPresenceRemoteSAP', 'AMT_RemoteAccessCredentialContext', 'AMT_RemoteAccessPolicyAppliesToMPS', 'AMT_RemoteAccessPolicyRule', '*AMT_UserInitiatedConnectionService', 'AMT_MPSUsernamePassword', 'AMT_PublicKeyCertificate'];
            // ###END###{!Certificates}
            if (amtversion > 11) { requests.push('*IPS_HTTPProxyService', 'IPS_HTTPProxyAccessPoint'); }
            amtstack.BatchEnum(null, requests, processRemote1);
        }

        function processRemote1(stack, name, responses, status) {
            if ((amtversion > 11) && (status == 400)) {
                // Check if only the HTTP proxy objects failed
                status = 200;
                if (responses['IPS_HTTPProxyAccessPoint'].status == 400) { delete responses['IPS_HTTPProxyAccessPoint']; }
                if (responses['IPS_HTTPProxyService'].status == 400) { delete responses['IPS_HTTPProxyService']; }
                for (var i in responses) { if (responses[i].status != 200) { status = responses[i].status; } }
            }
            if (status == 400) return;
            if ((errcheck(status, stack)) || (responses['AMT_UserInitiatedConnectionService'] == undefined || responses['AMT_UserInitiatedConnectionService'].response == undefined)) return;
            QV('go17', true); // Remote Access
            xxRemoteAccess = responses;
            xxEnvironementDetection = responses['AMT_EnvironmentDetectionSettingData'].response;
            xxEnvironementDetection['DetectionStrings'] = MakeToArray(xxEnvironementDetection['DetectionStrings']);
            xxCiraServers = responses['AMT_ManagementPresenceRemoteSAP'].responses;
            xxUserInitiatedCira = responses['AMT_UserInitiatedConnectionService'].response;
            xxRemoteAccessCredentiaLinks = responses['AMT_RemoteAccessCredentialContext'].responses;
            xxMPSUserPass = responses['AMT_MPSUsernamePassword'].responses;

            // Figure out policies attached to servers. Create a policy type to server table.
            xxPolicies = { 'User': [], 'Alert': [], 'Periodic': [] };
            for (var i in responses['AMT_RemoteAccessPolicyAppliesToMPS'].responses) {
                var policy = responses['AMT_RemoteAccessPolicyAppliesToMPS'].responses[i];
                var server = Clone(getItem(xxCiraServers, 'Name', getItem(policy['ManagedElement']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'Name')['Value']));
                server.MpsType = policy['MpsType']; // MpsType was added in Intel AMT 11.6
                var ptype = (getItem(policy['PolicySet']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyRuleName')['Value']).split(' ')[0];
                xxPolicies[ptype].push(server);
            }

            updateRemoteAccess();
        }

        function updateRemoteAccess() {
            if (xxEnvironementDetection == null) return;
            var x = '', e = "Disabilitato", ciraProxySupport = (xxRemoteAccess['IPS_HTTPProxyService'] && xxRemoteAccess['IPS_HTTPProxyAccessPoint']);
            if (xxEnvironementDetection['DetectionStrings'] && xxEnvironementDetection['DetectionStrings'].length > 0) { e = "Abilitato," + xxEnvironementDetection['DetectionStrings'].length + ' ' + (xxEnvironementDetection['DetectionStrings'].length > 1?'domains':'domain'); }

            // General settings
            x += TableStart();
            x += TableEntry("Rilevazione dell'ambiente", addLink(e, 'editEnvironmentDetection()'));
            x += TableEntry("Opzioni di avvio dell'utente", addLinkConditional(xxUserInitiatedEnabledState[xxUserInitiatedCira['EnabledState']], 'editUserInitiatedCira()', xxAccountAdminName));
            var y = ('<i>' + "Nessuna" + '</i>');
            if (xxPolicies['User'].length > 0) { y = ''; for (var i in xxPolicies['User']) { if (y.length > 0) y += ', '; y += xxPolicies['User'][i]['AccessInfo']; if (xxPolicies['User'][i].MpsType == 1) { y += ' (CILA)'; } } }
            x += TableEntry("Connessione avviata dall'utente", addLinkConditional(y, 'editMpsPolicy("User")', xxAccountAdminName));
            var y = ('<i>' + "Nessuna" + '</i>');
            if (xxPolicies['Alert'].length > 0) { y = ''; for (var i in xxPolicies['Alert']) { if (y.length > 0) y += ', '; y += xxPolicies['Alert'][i]['AccessInfo']; if (xxPolicies['Alert'][i].MpsType == 1) { y += ' (CILA)'; } } }
            x += TableEntry("Connessione avviata da avviso", addLinkConditional(y, 'editMpsPolicy("Alert")', xxAccountAdminName));
            var y = ('<i>' + "Nessuna" + '</i>');
            if (xxPolicies['Periodic'].length > 0) { y = ''; for (var i in xxPolicies['Periodic']) { if (y.length > 0) y += ', '; y += xxPolicies['Periodic'][i]['AccessInfo']; if (xxPolicies['Periodic'][i].MpsType == 1) { y += ' (CILA)'; } } }
            var periodicPolicy = getItem(xxRemoteAccess['AMT_RemoteAccessPolicyRule'].responses, "PolicyRuleName", "periodico");
            if (periodicPolicy) {
                var exdata = atob(periodicPolicy['ExtendedData']);
                if (ReadInt(exdata, 0) == 0) { y += format(", ogni {0} secondi", ReadInt(exdata, 4)); }
                if (ReadInt(exdata, 0) == 1) { var hours = ReadInt(exdata, 4); var minutes = ReadInt(exdata, 8); if (minutes < 10) minutes = '0' + minutes; y += ', at ' + hours + ":" + minutes + ' daily'; }
            }
            x += TableEntry("Connessione periodica", addLinkConditional(y, 'editMpsPolicy("Periodic")', xxAccountAdminName));
            x += TableEnd();

            // Show MPS servers
            x += '<br>';
            x += TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gestire i server di gestione remota Intel&reg; AMT." + '<br><br>';
            if (xxCiraServers.length == 0) {
                x += '<div style=padding-left:15px><br><i>' + "Nessun server remoto trovato." + '</i></div><br>';
            } else {
                for (var i in xxCiraServers) {
                    var desc = ':' + xxCiraServers[i]['Port'];
                    if (xxCiraServers[i]['CN']) desc += ', ' + xxCiraServers[i]['CN'];
                    x += '<div class=itemBar onclick=showServerDetails(' + i + ')><div style=padding-top:3px><b>' + xxCiraServers[i]['AccessInfo'] + '</b>' + EscapeHtml(desc) + '</div></div>';
                }
            }

            // Show MPS proxies if supported
            if (ciraProxySupport) {
                x += '<br>' + "Gestire i proxy HTTP utilizzati per le connessioni di gestione." + '<br><br>';
                var proxyService = xxRemoteAccess['IPS_HTTPProxyService'].response;
                var proxies = xxRemoteAccess['IPS_HTTPProxyAccessPoint'].responses;
                if (proxies.length == 0) {
                    x += '<div style=padding-left:15px><br><i>' + "Nessun proxy configurato." + '</i></div><br>';
                } else {
                    for (var i in proxies) {
                        //x += '<div class=itemBar onclick=showProxyDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(proxies[i]['AccessInfo']) + ':' + proxies[i]['ProxyPort'] + '</b> / ' + EscapeHtml(proxies[i]['NetworkDnsSuffix']) + '</div></div>';
                        x += '<div class=itemBar onclick=showProxyDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(proxies[i]['AccessInfo']) + ':' + proxies[i]['Port'] + '</b> / ' + EscapeHtml(proxies[i]['NetworkDnsSuffix']) + '</div></div>';
                    }
                }
            }

            var addserverbutton = '';
            if (xxAccountAdminName) {
                addserverbutton = AddButton("Aggiungi server...", 'AddRemoteAccessServer()');
                if (ciraProxySupport) { addserverbutton += AddButton("Aggiungi proxy ...", 'AddRemoteAccessProxy()'); }
            }
            x += '<br><td class=r1>' + TableEnd(AddRefreshButton('PullRemoteAccess()') + addserverbutton);

            QH('id_TableRemoteAccess', x);
        }

        var xxEditMpsPolicyType;
        function editMpsPolicy(type) {
            var x = '', cilaSupport = ((amtversion > 11) || ((amtversion == 11) && (amtversionmin >= 6)));
            xxEditMpsPolicyType = type;
            var name = xxEditMpsPolicyType;
            if (name == 'User') name = "Utente avviato";
            var policy = getItem(xxRemoteAccess['AMT_RemoteAccessPolicyRule'].responses, "PolicyRuleName", name);
            x += '<div style=height:26px><select id=d2server1 style=float:right;width:206px onchange=editMpsPolicyUpdate()>';
            x += '<option value=-1>' + "(Nessuna)";
            for (var i in xxCiraServers) { x += '<option value=' + i + '' + ((xxPolicies[type][0] && xxPolicies[type][0]['Name'] == xxCiraServers[i]['Name']) ? ' selected' : '') + '>' + xxCiraServers[i]['AccessInfo'] }
            x += '</select><div>' + "Server primario" + '</div></div>';
            if (cilaSupport) { x += '<div style=height:26px><select id=d2server1cira style=float:right;width:206px onchange=editMpsPolicyUpdate()><option value=0>' + "CIRA - Esterno" + '<option value=1' + (((xxPolicies[type][0]) && (xxPolicies[type][0].MpsType == 1))?' selected':'') + '>' + "CILA - Interno" + '</select><div>' + "Tipo di MPS primario" + '</div></div>'; }
            if (xxCiraServers.length > 1) {
                x += '<div style=height:26px><select id=d2server2 style=float:right;width:206px onchange=editMpsPolicyUpdate()>';
                x += '<option value=-1>' + "(Nessuna)";
                for (var i in xxCiraServers) { x += '<option value=' + i + '' + ((xxPolicies[type][1] && xxPolicies[type][1]['Name'] == xxCiraServers[i]['Name']) ? ' selected' : '') + '>' + xxCiraServers[i]['AccessInfo'] }
                x += '</select><div>' + "Server secondario" + '</div></div>';
                if (cilaSupport) { x += '<div style=height:26px><select id=d2server2cira style=float:right;width:206px onchange=editMpsPolicyUpdate()><option value=0>' + "CIRA - Esterno" + '<option value=1' + (((xxPolicies[type][1]) && (xxPolicies[type][1].MpsType == 1)) ? ' selected' : '') + '>' + "CILA - Interno" + '</select><div>' + "Tipo di MPS secondario" + '</div></div>'; }
            }
            var t, v = 0;
            if (policy) { v = policy['TunnelLifeTime']; }
            x += '<div style=height:26px><input id=d2lifetime style=float:right;width:200px onchange=editMpsPolicyUpdate() value=' + v + '>';
            x += '<div>' + "Durata del tunnel (secondi)" + '</div></div>';
            if (type == 'Periodic') {
                t = 0;
                v = 3600;
                if (policy) {
                    var xx = atob(policy['ExtendedData']);
                    t = ReadInt(xx, 0);
                    v = ReadInt(xx, 4);
                    if (t == 1) {
                        var mm = ReadInt(xx, 8);
                        if (mm < 10) mm = '0' + mm;
                        v += ':' + mm;
                    }
                }
                x += '<div style=height:26px><select id=d2ttype style=float:right;width:206px onchange=editMpsPolicyUpdate()>';
                x += '<option value=0' + (t == 0 ? ' selected' : '') + '>' + "Periodico, intervallo di tempo" + '<option value=1' + (t == 1 ? ' selected' : '') + '>' + "Ora del giorno, una volta al giorno";
                x += '</select><div>' + "Tipo di trigger" + '</div></div><div style=height:26px><input id=d2timer style=float:right;width:200px onkeyup=editMpsPolicyUpdate() value=' + v + '><div id=ttypelabel></div></div>';
            }
            setDialogMode(11, format("{0} Connessione", type), 3, editMpsPolicyOk, x);
            editMpsPolicyUpdate();
        }

        function editMpsPolicyUpdate() {
            var cilaSupport = ((amtversion > 11) || ((amtversion == 11) && (amtversionmin >= 6)));
            var ok = (xxCiraServers.length <= 1 || ((Q('d2server1').value == -1) || (Q('d2server1').value != Q('d2server2').value)));
            if (ok == true && xxEditMpsPolicyType == 'Periodic' && Q('d2ttype').value == 1) { var hhmm = Q('d2timer').value.split(':'); if (hhmm.length != 2) ok = false; else { var hh = parseInt(hhmm[0]); var mm = parseInt(hhmm[1]); if (hh < 0 || hh > 23 || mm < 0 || mm > 59) ok = false; } }
            QE('idx_dlgOkButton', ok);
            if (xxCiraServers.length > 1) QE('d2server2', Q('d2server1').value != -1);
            if (xxEditMpsPolicyType == 'Periodic') {
                QE('d2timer', Q('d2server1').value != -1);
                QH('ttypelabel', Q('d2ttype').value == 0 ? "Intervallo di trigger (secondi)" : "Ora del giorno (HH: MM)");
                QE('d2ttype', Q('d2server1').value != -1);
            }
            QE('d2lifetime', Q('d2server1').value != -1);

            // If we are on Intel AMT 11.6 or higher, enable the CIRA/CILA selector when needed.
            if (cilaSupport) {
                QE('d2server1cira', Q('d2server1').value > -1)
                if (xxCiraServers.length > 1) { QE('d2server2cira', (Q('d2server1').value > -1) && (Q('d2server2').value > -1)); }
            }
        }

        function editMpsPolicyOk() {
            var name = xxEditMpsPolicyType;
            if (name == 'User') { name = 'User Initiated'; }

            if (getItem(xxRemoteAccess['AMT_RemoteAccessPolicyRule'].responses, 'PolicyRuleName', name)) {
                // Remove old policy
                amtstack.Delete('AMT_RemoteAccessPolicyRule', { 'PolicyRuleName': name }, editMpsPolicyOk2);
            } else {
                // No old policy to remove, skip this.
                editMpsPolicyOk2();
            }
        }

        function editMpsPolicyOk2(stack, name, responses, status) {
            var cilaSupport = ((amtversion > 11) || ((amtversion == 11) && (amtversionmin >= 6)));
            if (Q('d2server1').value == -1) { PullRemoteAccess(); return; }

            var trigger = 0;
            if (xxEditMpsPolicyType == 'Alert') trigger = 1;
            if (xxEditMpsPolicyType == 'Periodic') trigger = 2;

            // Setup extended data
            var extendedData = null;
            if (trigger == 2) {
                var timertype = Q('d2ttype').value;
                var exdata = IntToStr(Q('d2timer').value); // Interval trigger
                if (timertype == 1) { var hhmm = Q('d2timer').value.split(':'); exdata = IntToStr(parseInt(hhmm[0])) + IntToStr(parseInt(hhmm[1])); } // Time of day trigger
                extendedData = btoa(IntToStr(timertype) + exdata);
            }

            // Create the MPS server references
            var server1, server2;
            if (Q('d2server1').value >= 0) { server1 = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="Name">' + xxCiraServers[Q('d2server1').value]['Name'] + '</Selector></SelectorSet></ReferenceParameters>'; }
            if (Q('d2server1').value >= 0 && xxCiraServers.length > 1 && Q('d2server2').value >= 0) { server2 = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="Name">' + xxCiraServers[Q('d2server2').value]['Name'] + '</Selector></SelectorSet></ReferenceParameters>'; }

            // Put the CIRA/CILA servers in the right bins.
            var ciraServers = [];
            var cilaServers = [];
            if (cilaSupport) {
                // Only Intel AMT 11.6 supports this
                if (server1) {
                    if (Q('d2server1cira').value == 0) { ciraServers.push(server1); } else { cilaServers.push(server1); }
                    if (server2) { if (Q('d2server2cira').value == 0) { ciraServers.push(server2); } else { cilaServers.push(server2); } }
                }
            } else {
                // If older than Intel AMT 11.6, put all servers in the CIRA bucket.
                if (server1) { ciraServers.push(server1); if (server2) { ciraServers.push(server2); } }
            }

            // Go ahead and create the new CIRA/CILA policy.
            amtstack.AMT_RemoteAccessService_AddRemoteAccessPolicyRule(trigger, Q('d2lifetime').value, extendedData, ciraServers, cilaServers, PullRemoteAccess);
        }

        var editEnvironmentDetectionTmp;
        function editEnvironmentDetection(a) {
            if (a != 1) { editEnvironmentDetectionTmp = (xxEnvironementDetection['DetectionStrings']) ? Clone(xxEnvironementDetection['DetectionStrings']) : []; }
            var x = '';
            if (xxAccountAdminName) x += "Immettere fino a 5 suffissi di dominio Intranet. Se il computer si trova al di fuori di questi domini, le porte locali Intel&reg; AMT verranno chiuse e le connessioni del server remoto saranno attive." + '<br><br>';
            if (editEnvironmentDetectionTmp.length == 0) { x += '<i>' + "Nessun dominio intranet, Rilevamento ambiente disabilitato." + '</i><br>'; }
            for (var i in editEnvironmentDetectionTmp) { x += '<div class=itemBar style=margin-right:0><div style=float:right>' + AddButton2("Rimuovere", 'editEnvironmentDetectionRemove(' + i + ')') + '</div><div style=padding-top:3px;max-width:260px;overflow:hidden title="' + editEnvironmentDetectionTmp[i] + '"><b>' + editEnvironmentDetectionTmp[i] + '</b></div></div>'; }
            if (xxAccountAdminName && editEnvironmentDetectionTmp.length < 5) { x += '<br><input id=edInput placeholder=intranet.org style=width:276px onkeyup=edInputChg() maxlength=63><input type=button id=edAdd value=Add style=width:80px;margin-left:5px onclick=editEnvironmentDetectionAdd()>'; }
            if (a == 1) QH('id_dialogOptions', x); else setDialogMode(11, "Rilevamento dell'ambiente", xxAccountAdminName?3:1, editEnvironmentDetectionDlg, x);
            edInputChg();
        }

        function editEnvironmentDetectionDlg() {
            if (xxAccountAdminName) {
                var t = Clone(xxEnvironementDetection);
                t['DetectionStrings'] = editEnvironmentDetectionTmp;
                //console.log('AMT_EnvironmentDetectionSettingData', t);
                amtstack.Put('AMT_EnvironmentDetectionSettingData', t, editEnvironmentDetectionDlg2, 0, 1);
            }
        }

        function editEnvironmentDetectionDlg2(stack, name, response, status) {
            if (status != 200) { messagebox("Rilevamento dell'ambiente", format("Impossibile aggiungere il server, stato {0}", status)); }
            else if ((response.Body['ReturnValue']) && (response.Body['ReturnValue'] != 0)) { messagebox("Rilevamento dell'ambiente", response.Body.ReturnValueStr.replace(/_/g, ' ')); }
            else { PullRemoteAccess(); }
        }

        function edInputChg() {
            if (editEnvironmentDetectionTmp.length < 5) QE('edAdd', Q('edInput').value.length > 0);
        }

        function editEnvironmentDetectionAdd() {
            editEnvironmentDetectionTmp.push(Q('edInput').value);
            editEnvironmentDetection(1);
        }

        function editEnvironmentDetectionRemove(h) {
            editEnvironmentDetectionTmp.splice(h, 1);
            editEnvironmentDetection(1);
        }

        function editUserInitiatedCira() {
            if (xxdialogMode) return;
            var s = '';
            for (var i in xxUserInitiatedEnabledState) { s += '<input type=radio name=d11 id=wl' + i + ' value=' + i + ' ' + ((xxUserInitiatedCira['EnabledState'] == i) ? 'checked' : '') + '>' + xxUserInitiatedEnabledState[i] + '<br>'; }
            setDialogMode(11, "Tunnel avviato dall'utente", 3, editUserInitiatedCiraDlg, s);
        }

        function editUserInitiatedCiraDlg() { amtstack.AMT_UserInitiatedConnectionService_RequestStateChange(document.querySelector('input[name=d11]:checked').value, null, editUserInitiatedCiraDlg2); }
        function editUserInitiatedCiraDlg2(stack, name, response, status) { if (status == 200) { amtstack.Get('AMT_UserInitiatedConnectionService', editUserInitiatedCiraDlg3, 0, 1); } }
        function editUserInitiatedCiraDlg3(stack, name, response, status) { if (status == 200) { xxUserInitiatedCira = response.Body; updateRemoteAccess(); } }

        var xxShowServerDetailsHandle;
        function showServerDetails(h) {
            xxShowServerDetailsHandle = h;
            var server = xxCiraServers[h];
            var x = '';
            x += addHtmlValue("Nome d'accesso", server['AccessInfo']);
            if (server['Port']) x += addHtmlValue("Porta", server['Port']);
            if (server['CN']) x += addHtmlValue("Nome comune", server['CN']);

            var credentiallink = getElementWithContextSelectorValue(xxRemoteAccessCredentiaLinks, server['Name']);
            if (credentiallink) {
                var credentialselectorvalue = credentiallink['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                if (credentialselectorvalue.indexOf('Username') > 0) {
                    x += addHtmlValue("Tipo di autenticazione", "TLS User & Pass / Server-Auth");
                    x += addHtmlValue("ID remoto", getInstance(xxMPSUserPass, credentialselectorvalue)['RemoteID']);
                } else {
                    x += addHtmlValue("Tipo di autenticazione", "Certificato / Autenticazione reciproca TLS");
                    // ###BEGIN###{!Certificates}
                    var c = getInstance(xxRemoteAccess['AMT_PublicKeyCertificate'].responses, credentialselectorvalue);
                    // ###END###{!Certificates}
                    // ###BEGIN###{Certificates}
                    var c = getInstance(xxCertificates, credentialselectorvalue);
                    // ###END###{Certificates}
                    x += addHtmlValue("Nome del certificato", parseCertName(c['Subject'])['CN']);
                }
            }

            var buttons = 1;
            if (xxAccountAdminName) buttons = 5;
            setDialogMode(11, "Server remoto #" + (h + 1), buttons, showServerDetailsOk, x);
        }

        function getElementWithContextSelectorValue(elements, value) {
            for (var i in elements) {
                elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector'] = MakeToArray(elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector']);
                for (var j in elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector']) { if (elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector'][j]['Value'] == value) return elements[i]; }
            }
            return null;
        }

        function showServerDetailsOk(r) {
            // Delete the selected CIRA server 
            if (r == 2) { amtstack.Delete('AMT_ManagementPresenceRemoteSAP', { 'Name': xxCiraServers[xxShowServerDetailsHandle]['Name'] }, showServerDetailsOk2); }
        }

        function showServerDetailsOk2(stack, name, responses, status) {
            if (status == 408) { messagebox("Rimozione del server remoto", "Impossibile rimuovere il server, accesso negato."); } else { PullRemoteAccess(); }
        }

        function parseCertName(x) {
            var j, r = {}, xx = x.split(',');
            for (var i in xx) { j = xx[i].indexOf('='); r[xx[i].substring(0, j)] = xx[i].substring(j + 1); }
            return r;
        }
        
        function showProxyDetails(h) {
            var proxy = xxRemoteAccess['IPS_HTTPProxyAccessPoint'].responses[h];

            var x = addHtmlValue("Nome d'accesso", proxy['AccessInfo'] + ':' + proxy['ProxyPort']);
            x += addHtmlValue("Suffisso DNS", proxy['NetworkDnsSuffix']);
            //x += addHtmlValue("Proxy type", ['Administrator', 'Operating system'][proxy['ProxyType']]);
            x += addHtmlValue("Tipo di proxy", ['Administrator', 'Operating system'][proxy['Type']]);
            //x += addHtmlValue("Last time used", proxy['LastTimeUsed']);

            var buttons = 1;
            if (xxAccountAdminName) { buttons = 5; }
            setDialogMode(11, "Numero proxy HTTP" + (h + 1), buttons, showProxyDetailsOk, x, h);
        }

        function showProxyDetailsOk(r, h) {
            // Delete the selected proxy server
            var proxy = xxRemoteAccess['IPS_HTTPProxyAccessPoint'].responses[h];
            if (r == 2) { amtstack.Delete('IPS_HTTPProxyAccessPoint', { 'Name': proxy['Name'] }, showProxyDetailsOk2); }
        }

        function showProxyDetailsOk2(stack, name, responses, status) {
            if (status == 408) { messagebox("Rimozione proxy HTTP", "Impossibile rimuovere il proxy HTTP, accesso negato."); } else { PullRemoteAccess(); }
        }

        function AddRemoteAccessProxy() {
            // AddRemoteAccessProxy Host name = 2, Ipv4 = 3, Ipv6 = 4
            var x = '<div style=height:26px><select id=d2type style=float:right;width:206px onchange=AddRemoteAccessProxyUpdate()><option value=2>' + "Nome host FQDN" + '<option value=3>' + "Indirizzo IPv4" + '<option value=4>' + "Indirizzo IPv6" + '</select><div>' + "Tipo di connessione" + '</div></div>';
            x += '<div style=height:26px><input id=d2host style=float:right;width:200px maxlength=255 onkeyup=AddRemoteAccessProxyUpdate()><div id=d2typespan></div></div>';
            x += '<div style=height:26px><input id=d2port onkeypress="return (event.charCode == 0 || (event.charCode >= 48 && event.charCode <= 57))" style=float:right;width:200px onkeyup=AddRemoteAccessProxyUpdate()><div>' + "Porta" + '</div></div>';
            x += '<div style=height:26px><input id=d2domain style=float:right;width:200px maxlength=191 onkeyup=AddRemoteAccessProxyUpdate()><div>' + "Suffisso DNS" + '</div></div>';
            setDialogMode(11, "Aggiungi proxy HTTP", 3, AddRemoteAccessProxyOk, x);
            AddRemoteAccessProxyUpdate();
        }

        function AddRemoteAccessProxyUpdate() {
            var ok = (Q('d2host').value.length != 0) && (Q('d2domain').value.length != 0);
            if ((Q('d2port').value.length == 0) || (parseInt(Q('d2port').value) > 65535)) { ok = false; }
            QE('idx_dlgOkButton', ok);
            QH('d2typespan', ['', '', "FQDN / nome host", "Indirizzo IPv4", "Indirizzo IPv6"][Q('d2type').value]);
        }

        function AddRemoteAccessProxyOk() {
            amtstack.IPS_HTTPProxyService_AddProxyAccessPoint(Q('d2host').value, Q('d2type').value, parseInt(Q('d2port').value), Q('d2domain').value, AddRemoteAccessProxyOk2);
        }

        function AddRemoteAccessProxyOk2(stack, name, response, status) {
            if (status != 200) {
                messagebox("Aggiungi server proxy", "Impossibile aggiungere proxy, stato" + status);
            } else if (response.Body['ReturnValue'] != 0) {
                messagebox("Aggiungi server proxy", response.Body.ReturnValueStr.replace(/_/g, ' '));
            } else {
                PullRemoteAccess();
            }
        }

        function AddRemoteAccessServer() {
            // ###BEGIN###{!Certificates}
            var certs = xxRemoteAccess['AMT_PublicKeyCertificate'].responses;
            // ###END###{!Certificates}
            // ###BEGIN###{Certificates}
            var certs = [];
            for (var i in xxCertificates) { if (xxCertificates[i].XPrivateKey) { certs.push(xxCertificates[i]); } }
            // ###END###{Certificates}
            var x = '';
            x += '<div style=height:26px><select id=d2type style=float:right;width:206px onchange=AddRemoteAccessServerUpdate()><option value=201>' + "Nome host FQDN" + '<option value=3>' + "Indirizzo IPv4" + '</select><div>' + "Tipo di connessione" + '</div></div>';
            x += '<div style=height:26px><input id=d2name style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div id=d2lname></div></div>';
            x += '<div style=height:26px><input id=d2port onkeypress="return (event.charCode == 0 || (event.charCode >= 48 && event.charCode <= 57))" style=float:right;width:200px value=4433 onkeyup=AddRemoteAccessServerUpdate()><div>' + "Porta del server" + '</div></div>';
            x += '<div style=height:26px id=d2ucn><input id=d2cn style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div>' + "Nome comune del server" + '</div></div>';
            x += '<div style=height:26px><select id=d2auth style=float:right;width:206px onchange=AddRemoteAccessServerUpdate()>';
            if (certs.length > 0) { x += '<option value=1>' + "Certificato"; }
            x += '<option value=2>' + "Nome utente / password" + '</select><div>' + "Tipo di autenticazione" + '</div></div>';
            x += '<span id=d2utype>';
            x += '<div style=height:26px><input id=d2user style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div>' + "Nome utente" + '</div></div>';
            x += '<div style=height:26px><input id=d2pass style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div>' + "Password sicura" + '</div></div>';
            x += '</span>';
            x += '<span id=d2ctype>';
            x += '<div style=height:26px><select id=d2cert style=float:right;width:206px onchange=AddRemoteAccessServerUpdate()>';
            for (var i in certs) { x += '<option value=' + certs[i]['InstanceID'].substring(34) + '>' + parseCertName(certs[i]['Subject'])['CN']; }
            x += '</select><div>' + "Certificato" + '</div></div></span>';
            setDialogMode(11, "Aggiungi server remoto", 3, AddRemoteAccessServerOk, x);
            AddRemoteAccessServerUpdate();
        }

        function AddRemoteAccessServerOk() {
            var cref, user, pass, cn;
            if (Q('d2auth').value == 1) {
                cref = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">Intel(r) AMT Certificate: Handle: ' + Q('d2cert').value + '</Selector></SelectorSet></ReferenceParameters>';
            } else {
                user = Q('d2user').value;
                pass = Q('d2pass').value;
            }
            if (Q('d2cn').value.length > 0) cn = Q('d2cn').value;
            amtstack.AMT_RemoteAccessService_AddMpServer(Q('d2name').value, Q('d2type').value, Q('d2port').value, Q('d2auth').value, cref, user, pass, cn, AddRemoteAccessServerOk2);
        }

        function AddRemoteAccessServerOk2(stack, name, response, status) {
            if (status != 200) {
                messagebox("Aggiungi Internet Server", format("Impossibile aggiungere il server, stato {0}", status));
            } else if (response.Body['ReturnValue'] != 0) {
                messagebox("Aggiungi Internet Server", response.Body.ReturnValueStr.replace(/_/g, ' '));
            } else {
                PullRemoteAccess();
            }
        }

        function AddRemoteAccessServerUpdate() {
            var ok = (Q('d2name').value.length != 0);
            if (Q('d2type').value == 3 && ok == true)  { ok = (Q('d2cn').value.length != 0); }
            if (Q('d2auth').value == 2 && ok == true) { ok = ((Q('d2user').value.length != 0) && (passwordcheck(Q('d2pass').value))); }
            if ((Q('d2port').value.length == 0) || (parseInt(Q('d2port').value) > 65535)) { ok = false; }
            if ((Q('d2name').value.indexOf(':') != -1) || ((Q('d2type').value == 3) && (Q('d2cn').value.indexOf(':') != -1))) { ok = false; }
            QH('d2lname', (Q('d2type').value == 201) ? "Nome host" : "Indirizzo IPv4");
            QV('d2utype', Q('d2auth').value == 2);
            QV('d2ucn', Q('d2type').value == 3);
            QV('d2ctype', Q('d2auth').value == 1);
            QE('idx_dlgOkButton', ok);
        }

        // ###END###{RemoteAccess}

        //
        // Edit Computer Name & DNS feature
        //

        function showEditNameDlg(x) {
            if (xxdialogMode) return;
            var t = amtsysstate['AMT_GeneralSettings'].response['HostName'], y = amtsysstate['AMT_GeneralSettings'].response['DomainName'];
            if (y != null && y.length > 0) t += '.' + y;
            var r = '<br><div style=height:26px><input id=d11name value="' + t + '" style=float:right;width:200px><div>' + "Nome e dominio" + '</div></div>';
            if (x == 1) {
                var s = (amtsysstate['AMT_GeneralSettings'].response['SharedFQDN'] == true);
                r += '<div style=height:26px><select id=d11fqdn style=float:right;width:200px><option value=true ' + (s?'selected':'') + '>' + "Condiviso, come il sistema operativo" + '<option value="false" ' + (s?'':'selected') + '>' + "Dedicato, diverso dal sistema operativo" + '</select><div>' + "Condivisione del nome" + '</div></div>';
            }
            setDialogMode(11, "Nome del computer", 3, editNameDlgOk, r);
        }

        function editNameDlgOk() {
            var i = Q('d11name').value, j = i.indexOf('.'), k = '';
            if (j >= 0) { k = i.substring(j + 1); i = i.substring(0, j); }
            var clone = Clone(amtsysstate['AMT_GeneralSettings'].response);
            clone['HostName'] = i;
            clone['DomainName'] = k;
            if (Q('d11fqdn')) { clone['SharedFQDN'] = d11fqdn.value; }
            amtstack.Put('AMT_GeneralSettings', clone, function() { amtstack.Get('AMT_GeneralSettings', computerNameGet, 0, 1); }, 0, 1);
        }

        function computerNameGet(stack, name, response, status) {
            if (status == 200) { amtsysstate['AMT_GeneralSettings'].response = response.Body; updateSystemStatus(); }
        }

        function showEditDnsDlg() {
            if (xxdialogMode) return;
            var g = amtsysstate['AMT_GeneralSettings'].response;
            var v = 0;
            if (g['DDNSUpdateByDHCPServerEnabled'] == true) v = 1;
            if (g['DDNSUpdateEnabled'] == true) v = 2;
            idx_d23ddns.value = v;
            idx_d23interval.value = g['DDNSPeriodicUpdateInterval'];
            idx_d23ttl.value = g['DDNSTTL'];
            showEditDnsDlgChange();
            setDialogMode(23, "Client DNS dinamico", 3, showEditDnsDlgOk);
        }

        function showEditDnsDlgOk() {
            var clone = Clone(amtsysstate['AMT_GeneralSettings'].response);
            clone['DDNSUpdateEnabled'] = ((idx_d23ddns.value == 2)?true:false);
            clone['DDNSUpdateByDHCPServerEnabled'] = ((idx_d23ddns.value == 1)?true:false);
            if (idx_d23ddns.value == 2) {
                clone['DDNSPeriodicUpdateInterval'] = idx_d23interval.value;
                clone['DDNSTTL'] = idx_d23ttl.value;
            }
            amtstack.Put('AMT_GeneralSettings', clone, function() { amtstack.Get('AMT_GeneralSettings', computerNameGet, 0, 1); }, 0, 1);
        }

        function showEditDnsDlgChange() {
            QE('idx_d23interval', idx_d23ddns.value == 2);
            QE('idx_d23ttl', idx_d23ddns.value == 2);
        }

        //
        // Intel AMT Features
        //

        function showFeaturesDlg() {
            if (xxdialogMode || !xxAccountAdminName) return;
            idx_d9redir.checked = amtfeatures[0], idx_d9kvm.checked = amtfeatures[3], idx_d9ider.checked = amtfeatures[2], idx_d9sol.checked = amtfeatures[1];
            QV('idx_d9kvm_div', amtfeatures[3] != null);
            setDialogMode(9, "Funzionalità Intel&reg; AMT", 3, featuresDlgOk)
        }

        function featuresDlgOk() {
            var r = amtsysstate['AMT_RedirectionService'].response;
            r['ListenerEnabled'] = idx_d9redir.checked;
            r['EnabledState'] = 32768 + ((idx_d9ider.checked?1:0) + (idx_d9sol.checked?2:0));
            amtstack.AMT_RedirectionService_RequestStateChange(r['EnabledState'],
                function (stack, name, response, status) {
                    if (status != 200) { messagebox("Errore", "RedirectionService, RequestStateChange Error" + status); return; }
                    if (amtfeatures[3] != null) {
                        amtstack.CIM_KVMRedirectionSAP_RequestStateChange((idx_d9kvm.checked) ? 2 : 3, 0,
                        function (stack, name, response, status) {
                            if (status != 200) { messagebox("Errore", "KVMRedirectionSAP, errore RequestStateChange" + status); return; }
                            amtstack.Put('AMT_RedirectionService', r, function (stack, name, response, status) {
                                if (status != 200) { messagebox("Errore", "Errore PUT RedirectionService" + status); return; }
                                amtstack.Get('AMT_RedirectionService', featuresDlgGet1, 0, 1);
                                amtstack.Get('CIM_KVMRedirectionSAP', featuresDlgGet2, 0, 1)
                            }, 0, 1) }
                        );
                    }
                }
            );
        }

        function featuresDlgGet1(stack, name, response, status) {
            if (status == 200) { amtsysstate['AMT_RedirectionService'].response = response.Body; updateSystemStatus(); }
        }

        function featuresDlgGet2(stack, name, response, status) {
            if (status == 200) { amtsysstate['CIM_KVMRedirectionSAP'].response = response.Body; updateSystemStatus(); }
        }

        //
        // Intel AMT Boot Features
        //

        function showEnableBootServiceDlg() {
            if (xxdialogMode) return;
            if (amtsysstate['CIM_BootService'].response['EnabledState'] != null) {
                QV('d26rpediv', amtversion > 15);
                if (amtversion > 15) {
                    idx_d26rpe1.checked = (amtsysstate['CIM_BootService'].response['EnabledState'] & 2)
                    idx_d26rpe0.checked = !idx_d26rpe1.checked;
                }
                idx_d26ocr1.checked = (amtsysstate['CIM_BootService'].response['EnabledState'] & 1)
                idx_d26ocr0.checked = !idx_d26ocr1.checked;
            }
            setDialogMode(26, "Boot Features", 3, showEnableBootServiceDlgOk)
        }

        function showEnableBootServiceDlgOk() {
            var v = 32768 + parseInt(document.querySelector('input[name=d26a]:checked').value);
            if (amtversion > 15) { v += parseInt(document.querySelector('input[name=d26b]:checked').value); }
            amtstack.CIM_BootService_RequestStateChange(v, null, showEnableBootServiceDlgResponse, v);
        }

        function showEnableBootServiceDlgResponse(stack, name, response, status, tag) {
            if (status == 200) {
                if (response.Body['ReturnValueStr'] != 'SUCCESS') { messagebox("Boot Features Error", response.Body['ReturnValueStr']); }
                amtstack.Get('CIM_BootService', showEnableBootServiceDlgResponse2, tag);
                PullSystemStatus();
            } else {
                if (response.Header['WsmanError']) {
                    messagebox("Boot Features Error", response.Header['WsmanError'].replace(/_/g, ' '));
                } else {
                    messagebox("Boot Features Error", "Error, Status = " + status);
                }
            }
        }

        function showEnableBootServiceDlgResponse2(stack, name, response, status, tag) {
            if ((status == 200) && (response.Body['EnabledState'] != tag)) { messagebox("Boot Features Error", "Unable to set OCR/RPE, check that these features are enabled in BIOS."); }
        }

        //
        // Intel AMT User Consent
        //

        function showConsentDlg() {
            if (xxdialogMode) return;
            var optinrequired = amtsysstate['IPS_OptInService'].response['OptInRequired'];
            idx_d10none.checked = (optinrequired == 0);
            idx_d10kvm.checked = (optinrequired == 1);
            idx_d10all.checked = (optinrequired == 0xFFFFFFFF);
            setDialogMode(10, "Consenso dell'utente", 3, consentDlgOk)
        }

        function consentDlgOk() {
            amtsysstate['IPS_OptInService'].response['OptInRequired'] = document.querySelector('input[name=d10]:checked').value;
            amtstack.Put('IPS_OptInService', amtsysstate['IPS_OptInService'].response, function() { amtstack.Get('IPS_OptInService', consentGet, 0, 1); }, 0, 1);
        }

        function consentGet(stack, name, response, status) {
            if (status == 200) { PullSystemStatus(); }
        }

        //
        // NETWORK SETTINGS
        //

// ###BEGIN###{NetworkSettings}

        /*
        IPv6 %AddrType%:
            0 - Address generated from: fe80::/64 + Interface ID,
            1 - Address generated from: [Router advertised prefix] + [Interface ID],
            2 - Global IPv6 address obtained from DHCPv6 Server,
            3 - IPv6 unicast address configured by the user,
            4 - Returned by FW for IPv6 addresses that are not owned by FW (such as IPv6 router address, configuration server address etc.)

        IPv6 %AddrState%:
            0 - DAD is still in process for this address,
            1 - Address is valid and may be used for new communication,
            2 - Address is deprecated and should not be used for new communication,
            3 - Covers both the preferred and deprecated states,
            4 - The valid lifetime of the address has expired,
            5 - An interface ID collision has been detected for this address when performing DAD,
            6 - Returned by FW for IPv6 addresses that are not owned by FW (such as IPv6 router address, configuration server address etc.
        */
        // ipv6addrtype are element 0 to 4, ipv6addrstate are 5 and after. Merged both arrays to cut down size
        var ipv6addrtype = ["Link indirizzo locale", "Indirizzo locale di rete", "Indirizzo globale", "Configurato dall'utente", "Non autorizzato", "DAD in corso", "valido", "deprecato", "preferito / obsoleto", "scaduto", "collisione", "non autorizzato"];
        function showIPv6AddrDlg(netifid, addrstr) {
            if (xxdialogMode) return;
            var x = TableStart();
            t = addrstr.split(',');
            for (var i = 0; i < t.length; i += 3) {
                x += TableEntry('<b>' + t[i] + '</b><br><span style=font-size:10px>' + ipv6addrtype[t[i + 1]] + "," + ipv6addrtype[+t[i + 2] + 5] + '</span>', '');
            }
            setDialogMode(11, (netifid == 0 ? "Indirizzi IPv6 per interfaccia cablata" : "Indirizzi IPv6 per interfaccia wireless"), 1, null, x + TableEnd());
        }

        function showIPv6StateDlg(netifid, state) {
            if (xxdialogMode || !amtsysstate) return;
            var zz = amtsysstate['IPS_IPv6PortSettings'].responses[netifid];
            ipv6manual = (netifid == 0 && (isIpAddress(zz['IPv6Address']) || isIpAddress(zz['DefaultRouter']) || isIpAddress(zz['PrimaryDNS']) || isIpAddress(zz['SecondaryDNS'])));

            QV('id_d21manualdiv', netifid == 0);
            QV('id_d21subnetdiv', false);
            QV('d21o0', true);
            QV('d21l0', true);
            QH('d21l0', "IPv6 disabilitato");
            QH('d21l1', "IPv6 abilitato, automatico");
            QH('d21l2', "IPv6 abilitato, automatico + indirizzo manuale");
            d21o0.checked = !state;
            d21o1.checked = state && !ipv6manual;
            d21o2.checked = state && ipv6manual;
            idx_d21address.value = isIpAddress(zz['IPv6Address'],'');
            idx_d21gateway.value = isIpAddress(zz['DefaultRouter'],'');
            idx_d21dns1.value = isIpAddress(zz['PrimaryDNS'],'');
            idx_d21dns2.value = isIpAddress(zz['SecondaryDNS'],'');
            setDialogMode(21, (netifid == 0 ? "Supporto IPv6 per interfaccia cablata" : "Supporto IPv6 per interfaccia wireless"), 3, function () { showIPv6StateDlgOk(netifid) })
            updateIPSetupDlg();
        }

        function showIPv6StateDlgOk(netifid) {
            var selector = '<w:SelectorSet><w:Selector Name="InstanceID">Intel(r) IPS IPv6 Settings ' + netifid + '</w:Selector></w:SelectorSet>';
            var zz = amtsysstate['IPS_IPv6PortSettings'].responses[netifid];
            if (netifid == 0) { // We can only set IPv6 manual address for wired interface
                if (d21o1.checked) { // Fully automatic, clear all addresses
                    zz['IPv6Address'] = zz['DefaultRouter'] = zz['PrimaryDNS'] = zz['SecondaryDNS'] = '::';
                    amtstack.Put('IPS_IPv6PortSettings', zz, showIPv6StateDlgDone, null, 0, selector);
                }
                if (d21o2.checked) { // Manual, set addresses
                    zz['IPv6Address'] = (idx_d21address.value == '') ? '::' : idx_d21address.value.toLocaleLowerCase();
                    zz['DefaultRouter'] = (idx_d21gateway.value == '') ? '::' : idx_d21gateway.value.toLocaleLowerCase();
                    zz['PrimaryDNS'] = (idx_d21dns1.value == '') ? '::' : idx_d21dns1.value.toLocaleLowerCase();
                    zz['SecondaryDNS'] = (idx_d21dns2.value == '') ? '::' : idx_d21dns2.value.toLocaleLowerCase();
                    amtstack.Put('IPS_IPv6PortSettings', zz, showIPv6StateDlgDone, null, 0, selector);
                }
            }
            // This code enables/disables IPv6 for a given interface.
            var elementSettings = amtsysstate['CIM_ElementSettingData'].responses;
            for (var i = 0; i < elementSettings.length; i++) {
                if (elementSettings[i]['SettingData'] && elementSettings[i]['SettingData']['ReferenceParameters']['SelectorSet']['Selector']['Value'] == ('Intel(r) IPS IPv6 Settings ' + netifid)) {
                    var CreationClassName = getItem(elementSettings[i]['ManagedElement']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'CreationClassName').Value;
                    var DeviceID = getItem(elementSettings[i]['ManagedElement']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'DeviceID').Value;
                    var selector2 = '<w:SelectorSet><w:Selector Name="ManagedElement"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' + CreationClassName + '</w:ResourceURI><w:SelectorSet><w:Selector Name="CreationClassName">' + CreationClassName + '</w:Selector><w:Selector Name="DeviceID">' + DeviceID + '</w:Selector><w:Selector Name="SystemCreationClassName">CIM_ComputerSystem</w:Selector><w:Selector Name="SystemName">Intel(r) AMT</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector><w:Selector Name="SettingData"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://intel.com/wbem/wscim/1/ips-schema/1/IPS_IPv6PortSettings</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">Intel(r) IPS IPv6 Settings ' + netifid + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector></w:SelectorSet>';
                    var clone = Clone(elementSettings[i]);
                    clone['IsCurrent'] = ((d21o0.checked) ? 2 : 1);
                    amtstack.Put('CIM_ElementSettingData', clone, showIPv6StateDlgDone, null, 0, selector2);
                }
            }
        }

        function showIPv6StateDlgDone(stack, name, response, status) {
            if (status == 200) {
                amtsysstate = undefined;
                PullSystemStatus();
            } else {
                messagebox("Supporto IPv6", format("Impossibile impostare lo stato IPv6, errore {0}", status));
            }
        }

        function showPingActionDlg() {
            if (xxdialogMode) return;
            var g = amtsysstate['AMT_GeneralSettings'].response;
            var v = (g['PingResponseEnabled'] == true) + ((g['RmcpPingResponseEnabled'] == true) << 1);
            d20a.checked = (v == 0);
            d20b.checked = (v == 1);
            d20c.checked = (v == 2);
            d20d.checked = (v == 3);
            setDialogMode(20, "Risposta al ping Intel&reg; AMT", 3, showPingActionDlgOk);
        }

        function showPingActionDlgOk() {
            var clone = Clone(amtsysstate['AMT_GeneralSettings'].response);
            var v = document.querySelector('input[name=d20]:checked').value;
            clone['PingResponseEnabled'] = ((v & 1) != 0);
            clone['RmcpPingResponseEnabled'] = ((v & 2) != 0);
            amtstack.Put('AMT_GeneralSettings', clone, PullSystemStatus, 0, 1);
        }

        function showIPSetupDlg() {
            if ((xxdialogMode) || (amtsysstate == null)) return;
            var x = amtsysstate['AMT_EthernetPortSettings'].responses[0];
            QV('id_d21ipaddrsync', amtversion > 6);
            if (amtversion > 6) { Q('d21ipsync').checked = x['IpSyncEnabled']; };
            QV('id_d21manualdiv', true);
            QV('id_d21subnetdiv', true);
            QV('d21o0', false);
            QV('d21l0', false);
            QH('d21l1', "Configurazione automatica tramite server DHCP");
            QH('d21l2', "Configurazione statica utilizzando le impostazioni IPv4 di seguito");
            d21o1.checked = (x['DHCPEnabled'] == true);
            d21o2.checked = !d21o1.checked;
            idx_d21address.value = isIpAddress(x['IPAddress'],'');
            idx_d21subnet.value = isIpAddress(x['SubnetMask'],'');
            idx_d21gateway.value = isIpAddress(x['DefaultGateway'],'');
            idx_d21dns1.value = isIpAddress(x['PrimaryDNS'],'');
            idx_d21dns2.value = isIpAddress(x['SecondaryDNS'],'');
            updateIPSetupDlg();
            setDialogMode(21, "Impostazioni IPv4", 3, showIPSetupDlgOk)
        }

        function updateIPSetupDlg() {
            var ok = true;
            if (d21o2.checked && (Q('d21l2').innerHTML == "IPv6 abilitato, automatico + indirizzo manuale") && (idx_d21address.value.split(':').length < 2)) { ok = false; }
            QE('idx_dlgOkButton', ok);
            idx_d21address.disabled = idx_d21subnet.disabled = idx_d21gateway.disabled = idx_d21dns1.disabled = idx_d21dns2.disabled = !(d21o2.checked && ((amtversion < 7) || (Q('d21ipsync').checked == false)));
        }

        function showIPSetupDlgOk() {
            var x = Clone(amtsysstate['AMT_EthernetPortSettings'].responses[0]);
            x['DHCPEnabled'] = d21o1.checked;
            delete x['IPAddress'];
            delete x['SubnetMask'];
            delete x['DefaultGateway'];
            delete x['PrimaryDNS'];
            delete x['SecondaryDNS'];
            if (amtversion > 6) { x['IpSyncEnabled'] = Q('d21ipsync').checked; }
            if ((d21o1.checked == false) && (Q('d21ipsync').checked == false)) { // || (amtversion < 7)
                x['IPAddress'] = idx_d21address.value;
                x['SubnetMask'] = idx_d21subnet.value;
                x['DefaultGateway'] = idx_d21gateway.value;
                if (idx_d21dns1.value != '') x['PrimaryDNS'] = idx_d21dns1.value;
                if (idx_d21dns2.value != '') x['SecondaryDNS'] = idx_d21dns2.value;
            }
            amtstack.Put('AMT_EthernetPortSettings', x, showIPSetupDlgDone, 0, 1, x);
        }

        function showIPSetupDlgDone(stack, name, response, status) {
            if (status == 200) {
                amtsysstate = undefined;
                PullSystemStatus();
            } else {
                messagebox("Impostazioni IPv4", format("Impossibile impostare i parametri di rete, errore {0}", status));
            }
        }

// ###END###{NetworkSettings}

// ###BEGIN###{PowerControl}

        //
        // POWER ACTIONS
        //

        amtPowerBootCapabilities = null;
        function showPowerActionDlg() {
            if (xxdialogMode) return;
            statusbox("Azioni di potere", "Verifica delle funzionalità ...");
            amtstack.Get('AMT_BootCapabilities', powerActionResponse00, 0, 1);
        }

        function showPowerActionDlg() {
            if (xxdialogMode) return;
            var powerState = 3;
            try {
                var x = amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'];
                if (x == 2) { powerState = 1; } else { powerState = 2; }
            } catch (ex) { }
            amtPowerBootCapabilities = amtsysstate['AMT_BootCapabilities'].response;
            QH('d5actionSelect', '');
            if (powerState & 2) { addOption('d5actionSelect', "Accendere", 2); }
            if (powerState & 1) {
                addOption('d5actionSelect', "Ripristina", 10);
                addOption('d5actionSelect', "Ciclo di alimentazione", 5);
                addOption('d5actionSelect', "Spegnere", 8);
            }
            if (amtPowerBootCapabilities['ForceDiagnosticBoot'] == true) {
                if (powerState & 2) { addOption('d5actionSelect', "Accendi la diagnostica", 300); }
                if (powerState & 1) { addOption('d5actionSelect', "Ripristina diagnostica", 301); }
            }
            if ((amtversion > 9) && (powerState & 1)) {
                addOption('d5actionSelect', "OS Wake from Standby", 500);
                addOption('d5actionSelect', "Risparmio energetico del sistema operativo", 501);
                addOption('d5actionSelect', "Soft-off", 12);
                addOption('d5actionSelect', "Soft-reset", 14);
                addOption('d5actionSelect', "Dormire", 4);
                addOption('d5actionSelect', "Hibernate", 7);
            }
            if (amtPowerBootCapabilities['BIOSSetup'] == true) {
                if (powerState & 2) { addOption('d5actionSelect', "Accensione al BIOS", 100); }
                if (powerState & 1) { addOption('d5actionSelect', "Ripristina al BIOS", 101); }
            }
            if (amtPowerBootCapabilities['SecureErase'] == true) {
                if (powerState & 2) { addOption('d5actionSelect', "Accensione per Cancellazione sicura", 104); }
                if (powerState & 1) { addOption('d5actionSelect', "Ripristina per cancellare sicura", 105); }
            }
            if ((amtPowerBootCapabilities['PlatformErase'] != null) && (amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && (amtsysstate['CIM_BootService'].response['EnabledState'] & 2)) {
                if (powerState & 2) { addOption('d5actionSelect', "Power up to Platform Erase", 106); }
                if (powerState & 1) { addOption('d5actionSelect', "Reset to Platform Erase", 107); }
            }
            // ###BEGIN###{IDER}
            if (powerState & 1) { addOption('d5actionSelect', "Ripristina IDE-R Floppy", 200); }
            if (powerState & 2) { addOption('d5actionSelect', "Accendi IDE-R Floppy", 201); }
            if (powerState & 1) { addOption('d5actionSelect', "Ripristinare su IDE-R CDROM", 202); }
            if (powerState & 2) { addOption('d5actionSelect', "Accendere il CD-ROM IDE-R", 203); }
            // ###END###{IDER}
            if (powerState & 1) { addOption('d5actionSelect', "Ripristina su PXE", 400); }
            if (powerState & 2) { addOption('d5actionSelect', "Accendere a PXE", 401); }
            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if (amtPowerBootCapabilities['ForceUEFIHTTPSBoot'] === true) {
                if (powerState & 1) { addOption('d5actionSelect', "Reset to HTTPS Boot", 600); }
                if (powerState & 2) { addOption('d5actionSelect', "Power on to HTTPS Boot", 601); }
            }
            // ###END###{PowerControl-OneClick}
            addOption('d5actionSelect', "Azione personalizzata ...", 999);
            // ###END###{PowerControl-Advanced}
            if (amtversion > 5) { addOption('d5actionSelect', "Consenso dell'utente ...", 998); } // On AMT 5 and higher, offer the option of doing user consent alone.
            setDialogMode(5, "Azioni di potere", 3, powerActionDlgCheck);
        }

        // ###BEGIN###{PowerControl-Advanced}
        // ###BEGIN###{PowerControl-OneClick}
        function oneClickFileSelect() { QE('idx_dlgOkButton', Q('ocrfile').files.length == 1); }
        // ###END###{PowerControl-OneClick}
        // ###END###{PowerControl-Advanced}

        function powerActionDlgCheck() {
            AmtOcrPba = null;
            AmtOcrPbaLength = 0;
            var action = d5actionSelect.value;

            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if ((action == 600) || (action == 601)) {
                // ###BEGIN###{Mode-NodeWebkit}
                // If the connection to intel AMT is not TLS, warn and exit now.
                if (wsstack.comm.xtlsCertificate == null) { messagebox("Azione di potere", "This feature requires a TLS connection to Intel AMT"); return; }
                // ###END###{Mode-NodeWebkit}
                var x = "Select a disk image for remote boot." + '<br /><br /><input id=ocrfile type=file onchange=oneClickFileSelect() accept=".iso">';
                setDialogMode(11, "HTTPS Boot", 3, function () {
                    var files = Q('ocrfile').files;
                    if (files.length != 1) return;
                    setupWebServer(urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress);
                    webserver.setupBootImage(files[0].path, (urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress));
                    powerActionDlg();
                }, x);
                QE('idx_dlgOkButton', false);
                return;
            }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}

            if ((action == 500) || (action == 501)) {
                // Perform OS wake from standby or OS sleep (Intel AMT 10+)
                amtstack.RequestOSPowerStateChange((action == 501)?3:2, function (stack, name, response, status) {
                    if (status == 200) { QH('id_dialogMessage', "Azione di potenza completata."); } else { QH('id_dialogMessage', format("Errore azione alimentazione # {0}.", status)); }
                    setDialogMode(1, "Azione di potere", 0);
                    setTimeout(function () { setDialogMode(0); }, 1300);
                });
            } else if ((action == 104) || (action == 105)) {
                var x = ("Conferma l'esecuzione di Intel&reg; Remote Secure Erase?" + '<br>' + "Immettere la password di cancellazione sicura, se necessario." + '<br>');
                x += ('<br><div style=height:16px><input type=password id=rsepass maxlength=32 style=float:right;width:240px><div>' + "Parola d'ordine" + '</div></div>');
                x += ('<br><div style=color:red>' + "<b> ATTENZIONE: </b> Questo cancellerà i dati sul sistema remoto." + '</div>');
                // ###BEGIN###{Mode-NodeWebkit}
                if (wsstack.comm.xtlsFingerprint == null) { x += ('<div style=color:red>' + "<b> ATTENZIONE: </b> TLS non viene utilizzato, la password verrà inviata in chiaro." + '</div>'); }
                // ###END###{Mode-NodeWebkit}
                rsepass = 1;
                setDialogMode(11, "Azioni di potere", 3, powerActionDlg, x);
            } else if ((action == 106) || (action == 107)) {
                powerActionDlgRPE();
            // ###BEGIN###{PowerControl-OneClick}
            } else if ((action == 999) && (amtversion >= 15)) {
                statusbox("Azioni di potere", "Checking boot sources...");            
                amtstack.BatchEnum('', ['CIM_BootSourceSetting'], powerActionDlgCheck00, true);
            // ###END###{PowerControl-OneClick}
            } else {
                powerActionDlg();
            }
        }
        
        function powerActionDlgRPE(advanced) {
            var x = ("Confirm execution of Intel&reg; Remote Platform Erase?" + '<br>');
            x += ('<br><div style=color:red>' + "<b> ATTENZIONE: </b> Questo cancellerà i dati sul sistema remoto." + '</div>');
            var actionTaken = [], platfromEraseSupport = amtPowerBootCapabilities['PlatformErase'];
            if (platfromEraseSupport & (1 << 1)) { actionTaken.push('<label><input id=rpef1 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Pyrite Revert" + '</label>'); }
            if (platfromEraseSupport & (1 << 2)) { actionTaken.push('<label><input id=rpef2 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Secure Erase All SSDs" + '</label>'); }
            if (platfromEraseSupport & (1 << 3)) { actionTaken.push('<label><input id=rpef3 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Verify Storage Erase" + '</label>'); }
            if (platfromEraseSupport & (1 << 6)) { actionTaken.push('<label><input id=rpef6 type=checkbox onchange=powerActionDlgRPEValidate()>' + "TPM Clear" + '</label>'); }
            if (platfromEraseSupport & (1 << 16)) { actionTaken.push('<label><input id=rpef16 type=checkbox onchange=powerActionDlgRPEValidate()>' + "OEM Custom Action" + '</label>'); }
            if (platfromEraseSupport & (1 << 25)) { actionTaken.push('<label><input id=rpef25 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Clear BIOS NVM Variables" + '</label>'); }
            if (platfromEraseSupport & (1 << 26)) { actionTaken.push('<label><input id=rpef26 type=checkbox onchange=powerActionDlgRPEValidate()>' + "BIOS Reload of Golden Configuration" + '</label>'); }
            if (platfromEraseSupport & (1 << 31)) { actionTaken.push('<label><input id=rpef31 type=checkbox onchange=powerActionDlgRPEValidate()>' + "CSME Unconfigure" + '</label>'); }
            if (actionTaken.length > 0) { x += (format('<br />' + "Select the actions to take:" + '<br /><br /><div style=margin-left:16px>{0}</div><br />', actionTaken.join('<br />'))); }
            x += '<div id=rpepsid style=margin-top:4px;margin-bottom:4px;display:none>' + addHtmlValue("Pyrite PSID", '<input id=rpepsidx style=width:210px maxlength=64 type=input>') + '</div>';
            x += '<div id=rpessdpass style=margin-top:4px;margin-bottom:4px;display:none>' + addHtmlValue("SSD Master Password", '<input id=rpessdpassx style=width:210px maxlength=64 type=input>') + '</div>';
            x += '<div id=rpeeomdata style=margin-top:4px;margin-bottom:4px;display:none>' + addHtmlValue("OEM Data (HEX)", '<input id=rpeoemdatax style=width:210px maxlength=256 type=input>') + '</div>';
            setDialogMode(11, "Azioni di potere", 3, powerActionDlgRPEEx, x, advanced);
            QE('idx_dlgOkButton', false);
        }

        function powerActionDlgRPEValidate() {
            var rpeFlags = 0, platfromEraseSupport = amtPowerBootCapabilities['PlatformErase'], sf = [1, 2, 3, 6, 16, 25, 26, 31];
            for (var i in sf) { if (platfromEraseSupport & (1 << sf[i])) { if (Q('rpef' + sf[i]).checked) { rpeFlags += (1 << sf[i]); } } }
            QV('rpessdpass', rpeFlags & 4);
            QV('rpeeomdata', rpeFlags & (1 << 16));
            QE('idx_dlgOkButton', rpeFlags);
        }

        var platfromEraseTLV = null;
        function powerActionDlgRPEEx(b, advanced) {
            var rpeFlags = 0, platfromEraseSupport = amtPowerBootCapabilities['PlatformErase'], sf = [1, 2, 3, 6, 16, 25, 26, 31];
            for (var i in sf) { if (platfromEraseSupport & (1 << sf[i])) { if (Q('rpef' + sf[i]).checked) { rpeFlags += (1 << sf[i]); } } }
            var tlv = makeUefiBootParam(1, rpeFlags, 4), tlvlen = 1;
            if (rpeFlags & 2) { tlv += makeUefiBootParam(10, Q('rpepsidx').value); tlvlen++; }
            if (rpeFlags & 4) { tlv += makeUefiBootParam(20, Q('rpessdpassx').value); tlvlen++; }
            if ((rpeFlags & (1 << 16)) && (Q('rpeoemdatax').value != '')) { tlv += makeUefiBootParam(20, hex2rstr(Q('rpeoemdatax').value), null, 11); tlvlen++; }
            platfromEraseTLV = { tlv: btoa(tlv), tlvlen: tlvlen };
            if (advanced) {
                // Attempt user consent
                statusbox("Azione di potere", "Verifica dello stato ...");
                amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
            } else {
                powerActionDlg();
            }
        }

        // ###BEGIN###{PowerControl-OneClick}
        var AmtOcrPba = null;
        var AmtOcrPbaLength = 0;
        function powerActionDlgCheck00(stack, name, response, status) {
            if (status != 200) { messagebox("Azione di potere", format("GET CIM_BootSourceSetting, Error #{0}", status) + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); return; }
            var bootSources = response.CIM_BootSourceSetting.responses;
            AmtOcrPba = {};
            for (var i = 0; i < bootSources.length; i++) {
                var instanceid = bootSources[i]['InstanceID'];
                if ((instanceid != null) && instanceid.toString().startsWith('Intel(r) AMT: Force OCR UEFI Boot')) {
                    try {
                        var arr = instanceid.trim().split(' ');
                        idx = parseInt(arr[arr.length - 1]);
                        AmtOcrPba[parseInt(idx)] = { instance: bootSources[i]['BIOSBootString'], bootstr: bootSources[i]['BootString'] };
                        AmtOcrPbaLength++;
                    } catch (e) { }
                }
            }
            powerActionDlg();
        }
        // ###END###{PowerControl-OneClick}

        function powerActionDlg() {
            //if (amtversion == 0) return;
            //if (amtversion > 6) { amtstack.Get('IPS_OptInService', powerActionResponse0); } else { amtstack.Get('AMT_BootSettingData', powerActionResponse1); }
            var action = d5actionSelect.value;
            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) { showAdvPowerDlg(); return; }
            // ###END###{PowerControl-Advanced}
            if (action == 998) { amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1); return; }

            // Some actions will not work if KVM/SOL/IDER are connected. If we perform these, disconnect now.
            if ((action < 10) && (action > 2) && (urlvars['noredirdisconnect'] == null)) {
                // ###BEGIN###{Desktop}
                if (desktop.State == 3) connectDesktop();
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (terminal.State == 3) connectTerminal();
                // ###END###{Terminal}
                // ###BEGIN###{IDER}
                if ((ider != undefined) && (ider.state == 3)) iderStop();
                // ###END###{IDER}
            }

            statusbox("Azione di potere", "Verifica dello stato ...");
            if ((rsepass != null) && (rsepass === 1)) { rsepass = Q('rsepass').value; }

            var uc = true; // Check if we need to ask for user consent
            if (amtversion < 6) uc = false; // Below AMT 6, user consent does not exist.
            if ((currentView == 13) && (action == 8)) uc = false; // if in terminal, don't ask for it if power down.
            if ((currentView != 13) && (action <= 10)) uc = false; // if not in terminal, don't ask for basic operations.

            if (uc) {
                // Attempt user consent
                amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
            } else {
                // Skip user consent
                amtstack.Get('AMT_BootSettingData', powerActionResponse1, 0, 1);
            }
        }

        // ###BEGIN###{PowerControl-Advanced}
        var AvdPowerDlg;
        function showAdvPowerDlg() {
            try { Q('idx_d24Command').value = (amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] == 2)?10:2; } catch (ex) { }

            // Available force boot options
            var forceBootDeviceOptions = '<option value=0>None</option><option id="ForceDVDBootOption" value=1>Force CD/DVD Boot</option><option id="ForcePXEBootOption" value=2>Force PXE Boot</option><option id="ForceHDBootOption" value=3>Force Hard Disk Boot</option><option id="ForceDiagBootOption" value=4>Force Diagnostic Boot</option>';

            // Show boot capabilities
            QV('d24dBiosPause', amtPowerBootCapabilities['BIOSPause'] == true);
            QV('d24dBiosSecureBoot', amtPowerBootCapabilities['BIOSSecureBoot'] == true);
            QV('d24dReflashBios', amtPowerBootCapabilities['BIOSReflash'] == true);
            QV('d24dBiosSetup', amtPowerBootCapabilities['BIOSSetup'] == true);
            QV('ForceDVDBootOption', amtPowerBootCapabilities['ForceCDorDVDBoot'] == true);
            QV('ForceDiagBootOption', amtPowerBootCapabilities['ForceDiagnosticBoot'] == true);
            QV('ForceHDBootOption', amtPowerBootCapabilities['ForceHardDriveBoot'] == true);
            //QV('', amtPowerBootCapabilities['ForceHardDriveSafeModeBoot'] == true);
            //QV('', amtPowerBootCapabilities['ForceWinREBoot'] == true);
            QV('ForcePXEBootOption', amtPowerBootCapabilities['ForcePXEBoot'] == true);
            // ###BEGIN###{PowerControl-OneClick}
            if ((AmtOcrPbaLength > 0) && (amtPowerBootCapabilities['ForceUEFIPBABoot'] == true)) {
                forceBootDeviceOptions += '<option id="ForceUEFIBootOption" value=5>Force OCR UEFI Boot Option</option>';
                var x = '';
                for (var i in AmtOcrPba) { x += '<option value=' + i + '>' + AmtOcrPba[i].instance + '</option>'; }
                QH('idx_d24customBootMediaIndex', x);
            }
            var httpsBootPossible = ((meshCentralServer == null) && (wsstack.comm.xtlsCertificate != null)) || (meshCentralServer!=null && ((currentcomputer.conn & 4) == 4) &&  currentcomputer.tls == 1) || (meshCentralServer!=null && ((currentcomputer.conn & 2) == 2) )
            if ((amtPowerBootCapabilities['ForceUEFIHTTPSBoot'] == true) && httpsBootPossible) { forceBootDeviceOptions += '<option id="ForceHttpBootOption" value=6>Force OCR UEFI HTTPS Boot (.iso)</option>'; }
            if ((amtPowerBootCapabilities['ForceUEFIHTTPSBoot'] == true) && httpsBootPossible) { forceBootDeviceOptions += '<option id="ForceHttpUrlBootOption" value=7>Force OCR UEFI HTTPS Boot (url)</option>'; }
            // ###END###{PowerControl-OneClick}
            QV('d24dForceProgressEvents', amtPowerBootCapabilities['ForcedProgressEvents'] == true);
            QV('d24dUseIDER', amtPowerBootCapabilities['IDER'] == true);
            QV('d24dLockKeyboard', amtPowerBootCapabilities['KeyboardLock'] == true);
            QV('d24dLockPowerButton', amtPowerBootCapabilities['PowerButtonLock'] == true);
            QV('d24dLockResetButton', amtPowerBootCapabilities['ResetButtonLock'] == true);
            QV('d24dSerialOverLan', amtPowerBootCapabilities['SOL'] == true);
            QV('d24dSecureErase', amtPowerBootCapabilities['SecureErase'] == true);
            QV('d24dPlatformErase', (amtPowerBootCapabilities['PlatformErase'] != null) && (amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && ((amtsysstate['CIM_BootService'].response['EnabledState'] & 2) != 0));
            QV('d24dFirmwareReset', amtPowerBootCapabilities['ConfigurationDataReset'] == true);
            QV('d24dLockSleepButton', amtPowerBootCapabilities['SleepButtonLock'] == true);
            QV('d24dUserPasswordBypass', amtPowerBootCapabilities['UserPasswordBypass'] == true);
            QV('idx_d24Verbocity1', amtPowerBootCapabilities['VerbosityQuiet'] == true);
            QV('idx_d24Verbocity2', amtPowerBootCapabilities['VerbosityVerbose'] == true);
            QV('idx_d24Verbocity3', amtPowerBootCapabilities['VerbosityScreenBlank'] == true);
            QV('d24p500', amtversion > 9);
            QV('d24p501', amtversion > 9);

            QH('idx_d24ForceBootDevice', forceBootDeviceOptions);
            setDialogMode(24, "Azione di potenza personalizzata", 3, showAdvPowerDlgOk);
            showAdvPowerDlgChange();
        }

        function showAdvPowerDlgChange() {
            var ok = true;
            QV('idd_d24IDERBootDevice', Q('d24UseIDER').checked);
            QV('idd_d24RSEPass', Q('d24SecureErase') ? Q('d24SecureErase').checked : false);
            // ###BEGIN###{Mode-NodeWebkit}
            QV('idd_d24RSEPassTlsWarn', (wsstack.comm.xtlsFingerprint == null) && (Q('d24SecureErase') ? Q('d24SecureErase').checked : false));
            // ###END###{Mode-NodeWebkit}

            // If this is a OS power state change, gray out all of the options.
            var ospower = ((Q('idx_d24Command').value >= 500) && (Q('idx_d24Command').value < 600));
            QE('idx_d24ForceBootDevice', !ospower);
            QE('idx_d24BootMediaIndex', !ospower);
            QE('idd_d24IDERBootDevice', !ospower);
            QE('idx_d24Verbocity', !ospower);
            QE('idd_d24RSEPass', !ospower);

            // If the boot source is not "None" (0), disable all boot settings.
            //var bootSettingOpts = ['d24BiosPause', 'd24BiosSecureBoot', 'd24BiosSetup', 'd24ForceProgressEvents', 'd24LockPowerButton', 'd24LockResetButton', 'd24LockSleepButton', 'd24LockKeyboard', 'd24UserPasswordBypass', 'd24ReflashBios', 'd24SafeMode', 'd24UseIDER', 'd24SerialOverLan', 'd24SecureErase'];
            //if ((idx_d24ForceBootDevice.value > 0) && (idx_d24ForceBootDevice.value < 5)) { for (var i in bootSettingOpts) { Q(bootSettingOpts[i]).checked = false; } }
            //for (var i in bootSettingOpts) { QE(bootSettingOpts[i], idx_d24ForceBootDevice.value == 0); }

            // ###BEGIN###{PowerControl-OneClick}
            var bootSourceIndex = Q('idx_d24ForceBootDevice').value;
            QV('idx_d24bootSource', bootSourceIndex < 5);
            QV('idx_d24customBootSource', bootSourceIndex == 5)
            QV('idx_d24diskImage', bootSourceIndex == 6);
            QV('idx_d24diskImageUrl', bootSourceIndex == 7);
            QV('idx_d24diskImageHttpTimeout', (bootSourceIndex == 7) && (amtversion > 16));
            if ((bootSourceIndex == 6) && (Q('idx_d24ocrBootFile').files.length != 1)) { ok = false; }
            if ((bootSourceIndex == 7) && (Q('idx_d24ocrBootUrl').value.trim().toLowerCase().startsWith('https://') == false)) { ok = false; }
            if ((bootSourceIndex == 7) && (amtversion > 16)) {
                var timeout = parseInt(Q('idx_d24ocrBootHttpBootTimeout').value);
                if (isNaN(timeout) || (timeout > 65535) || (timeout < 0)) { ok = false; }
            }
            // ###END###{PowerControl-OneClick}

            QE('idx_dlgOkButton', ok);
        }

        function showAdvPowerDlgOk() {
            // ###BEGIN###{PowerControl-OneClick}
            var forceBootSelection = Q('idx_d24ForceBootDevice').value;
            // ###BEGIN###{Mode-NodeWebkit}            
            if (((forceBootSelection == 5) || (forceBootSelection == 6) || (forceBootSelection == 7)) && 
                (((meshCentralServer == null) && (wsstack.comm.xtlsCertificate == null)) || (meshCentralServer!=null && ((currentcomputer.conn & 4) == 4) &&  currentcomputer.tls == 0))) {
                messagebox("Azione di potere", "This feature requires a TLS connection to Intel AMT"); return;
            }
            // ###END###{Mode-NodeWebkit}
            if (forceBootSelection == 6) {
                var files = Q('idx_d24ocrBootFile').files;
                if (files.length == 1) {
                    setupWebServer(urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress);
                    webserver.setupBootImage(files[0].path, (urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress));
                }
            }
            // ###END###{PowerControl-OneClick}

            var action = Q('idx_d24Command').value;
            if ((action == 500) || (action == 501)) {
                // Perform OS wake from standby or OS sleep (Intel AMT 10+)
                amtstack.RequestOSPowerStateChange((action == 501) ? 3 : 2, function (stack, name, response, status) {
                    if (status == 200) { QH('id_dialogMessage', "Azione di potenza completata."); } else { QH('id_dialogMessage', format("Errore azione alimentazione # {0}.", status)); }
                    setDialogMode(1, "Azione di potere", 0);
                    setTimeout(function () { setDialogMode(0); }, 1300);
                });
            } else {
                // Fetch all of the user data
                AvdPowerDlg = {};
                AvdPowerDlg.Action = Q('idx_d24Command').value;
                AvdPowerDlg.BIOSPause = Q('d24BiosPause').checked;
                AvdPowerDlg.BIOSSecureBoot = Q('d24BiosSecureBoot').checked;
                AvdPowerDlg.BIOSSetup = Q('d24BiosSetup').checked;
                AvdPowerDlg.BootMediaIndex = Q('idx_d24BootMediaIndex').value;
                AvdPowerDlg.FirmwareVerbosity = Q('idx_d24Verbocity').value;
                AvdPowerDlg.ForcedProgressEvents = Q('d24ForceProgressEvents').checked;
                AvdPowerDlg.IDERBootDevice = Q('idx_d24IDERBootDevice').value; // 0 = Boot on Floppy, 1 = Boot on IDER
                AvdPowerDlg.LockKeyboard = Q('d24LockKeyboard').checked;
                AvdPowerDlg.LockPowerButton = Q('d24LockPowerButton').checked;
                AvdPowerDlg.LockResetButton = Q('d24LockResetButton').checked;
                AvdPowerDlg.LockSleepButton = Q('d24LockSleepButton').checked;
                AvdPowerDlg.ReflashBIOS = Q('d24ReflashBios').checked;
                AvdPowerDlg.UseIDER = Q('d24UseIDER').checked;
                AvdPowerDlg.UseSOL = Q('d24SerialOverLan').checked;
                AvdPowerDlg.UseSafeMode = Q('d24SafeMode').checked;
                AvdPowerDlg.UserPasswordBypass = Q('d24UserPasswordBypass').checked;
                AvdPowerDlg.SecureErase = Q('d24SecureErase').checked;
                AvdPowerDlg.PlatformErase = Q('d24PlatformErase').checked
                AvdPowerDlg.FirmwareReset = Q('d24FirmwareReset').checked;
                if ((AvdPowerDlg.SecureErase === true) && (Q('d24rsepass').value.length > 0)) { AvdPowerDlg.RSEPassword = Q('d24rsepass').value; }

                if (AvdPowerDlg.PlatformErase === true) {
                    // Ask additional information about RPE
                    powerActionDlgRPE(true);
                } else {
                    // Attempt user consent
                    statusbox("Azione di potere", "Verifica dello stato ...");
                    amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
                }
            }
        }
        // ###END###{PowerControl-Advanced}

        function powerActionResponse0(stack, name, response, status) {
            //if (errcheck(status, stack)) return; // TODO: If AMT 5 or below, this will error and we need to skip user consent.
            if (status != 200) {
                if (connectDesktopConsent) { connectDesktop(true); } else { messagebox("Azione di potere", format("Errore # {0}", status)); }
                return;
            }
            //console.log('powerActionResponse0(' + name + ',' + ObjectToString2(response) + ',' + status + ')');
            //console.log("OptInRequired:", response.Body['OptInRequired']);
            //console.log("OptInState:", response.Body['OptInState']);
            //console.log(response);
            if (((response.Body['OptInRequired'] == 0xFFFFFFFF) || (connectDesktopConsent && (response.Body['OptInRequired'] != 0))) && (response.Body['OptInState'] != 3) && (response.Body['OptInState'] != 4)) {
                if (response.Body['OptInState'] == 2) {
                    amtstack.IPS_OptInService_CancelOptIn(null);
                    d6ConsentText.value = ''; // Reset user consent code to empty
                    setDialogMode(6, "Consenso dell'utente", 11, powerActionSendConsent);
                    checkConsentDisplay();
                    consentChanged();
                    return;
                }
                //console.log("Opt-in Required.", response.Body['OptInRequired']);
                statusbox("Azione di potere", "Avvio dell'iscrizione in corso ...");
                amtstack.IPS_OptInService_StartOptIn(powerActionResponseC1, 0, 1);
            } else {
                if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); return; }
                if (d5actionSelect.value == 998) { messagebox("Consenso dell'utente", "Non è necessario il consenso dell'utente."); return; }
                statusbox("Azione di potere", "Ottenere le impostazioni di avvio ...");
                amtstack.Get('AMT_BootSettingData', powerActionResponse1, 0, 1);
            }
        }

        function powerActionResponseC1(stack, name, response, status) {
            //if (errcheck(status, stack)) return;
            //console.log('powerActionResponseC1', name, status, response);
            if (status != 200) { if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); } else { messagebox("Azione di potere", format("Errore n.", status)); } return; }
            //console.log("powerActionResponseC1(" + name + "," + ObjectToString2(response) + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); } else { messagebox("Errore di consenso dell'utente", response.Body.ReturnValueStr.replace(/_/g, ' ')); }
            } else {
                d6ConsentText.value = ''; // Reset user consent code to empty
                setDialogMode(6, "Consenso dell'utente", 11, powerActionSendConsent);
                checkConsentDisplay();
                consentChanged();

                // Check if the machine is powered down, if it is, power it up for user consent.
                amtstack.Enum('CIM_ServiceAvailableToElement', function(stack, name, responses, status) {
                    if (errcheck(status, stack)) return;
                    amtsysstate['CIM_ServiceAvailableToElement'].responses = responses;
                    updateSystemStatus();
                    if ((amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0)) {
                        if (amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] != 2) {
                            // System is not on, power it on now.
                            amtstack.RequestPowerStateChange(2, function (stack, name, response, status) { });
                        }
                    }
                });
            }
        }

        //function powerActionCancelConsent() { amtstack.IPS_OptInService_CancelOptIn(null); }

        function powerActionSendConsent(buttons) {
            console.log('powerActionSendConsent', buttons);
            if (buttons == 0) {
                // Cancel button
                amtstack.IPS_OptInService_CancelOptIn(function () { });
                connectDesktopConsent = false;
                desktop.Stop();
            } else {
                // OK Button
                statusbox("Azione di potere", "Invio del consenso dell'utente ...");
                amtstack.IPS_OptInService_SendOptInCode(d6ConsentText.value, powerActionResponseC2, 0, 1);
            }
        }

        function powerActionResponseC2(stack, name, response, status) {
            //if (errcheck(status, stack)) return;
            if (status != 200) { messagebox("Azione di potere", format("Errore # {0}", status)); return; }
            //console.log("powerActionResponseC2(" + name + "," + ObjectToString2(response) + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
            } else {
                if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); return; }
                if (d5actionSelect.value == 998) { messagebox("Consenso dell'utente", "Consenso dell'utente riuscito."); return; } // This was just a user consent request, no need to go further.
                statusbox("Azione di potere", "Verifica dello stato ...");
                amtstack.Get('AMT_BootSettingData', powerActionResponse1, 0, 1);
            }
        }

        function powerActionResponse1(stack, name, response, status) {
            //if (errcheck(status, stack)) return;
            if (status != 200) { messagebox("Azione di potere", format("Errore # {0}", status)); return; }
            //console.log("powerActionResponse1(" + name + "," + ObjectToString2(response) + "," + status + ")");
            var action = d5actionSelect.value;
            var r = response.Body;
            r['ConfigurationDataReset'] = false;

            // Clean up parameters
            delete r['WinREBootEnabled'];
            delete r['UEFILocalPBABootEnabled'];
            delete r['UEFIHTTPSBootEnabled'];
            delete r['SecureBootControlEnabled'];
            delete r['BootguardStatus'];
            delete r['OptionsCleared'];
            delete r['BIOSLastStatus'];
            delete r['UefiBootParametersArray'];
            delete r['RPEEnabled'];

            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) {
                r['BIOSPause'] = AvdPowerDlg.BIOSPause;
                r['EnforceSecureBoot'] = AvdPowerDlg.BIOSSecureBoot;
                r['BIOSSetup'] = AvdPowerDlg.BIOSSetup;
                r['BootMediaIndex'] = AvdPowerDlg.BootMediaIndex;
                r['FirmwareVerbosity'] = AvdPowerDlg.FirmwareVerbosity;
                r['ForcedProgressEvents'] = AvdPowerDlg.ForcedProgressEvents;
                r['IDERBootDevice'] = AvdPowerDlg.IDERBootDevice; // 0 = Boot on Floppy, 1 = Boot on IDER
                r['LockKeyboard'] = AvdPowerDlg.LockKeyboard;
                r['LockPowerButton'] = AvdPowerDlg.LockPowerButton;
                r['LockResetButton'] = AvdPowerDlg.LockResetButton;
                r['LockSleepButton'] = AvdPowerDlg.LockSleepButton;
                r['ReflashBIOS'] = AvdPowerDlg.ReflashBIOS;
                r['UseIDER'] = AvdPowerDlg.UseIDER;
                r['UseSOL'] = AvdPowerDlg.UseSOL;
                r['UseSafeMode'] = AvdPowerDlg.UseSafeMode;
                r['UserPasswordBypass'] = AvdPowerDlg.UserPasswordBypass;
                if (r['SecureErase'] != null) {
                    r['SecureErase'] = ((AvdPowerDlg.SecureErase) && (amtPowerBootCapabilities['SecureErase'] == true));
                    if ((r['SecureErase'] == true) && (AvdPowerDlg.RSEPassword)) { r['RSEPassword'] = AvdPowerDlg.RSEPassword; }
                }
                if (r['PlatformErase'] != null) {
                    if ((amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && (amtsysstate['CIM_BootService'].response['EnabledState'] & 2) && ((AvdPowerDlg.PlatformErase) && (amtPowerBootCapabilities['PlatformErase'] != null) && ((amtPowerBootCapabilities['PlatformErase'] & 1) != 0))) {
                        r['PlatformErase'] = true;
                        r['UefiBootParametersArray'] = platfromEraseTLV.tlv;
                        r['UefiBootNumberOfParams'] = platfromEraseTLV.tlvlen;
                    } else {
                        r['PlatformErase'] = false;
                    }
                }
                if (r['ConfigurationDataReset'] != null) { r['ConfigurationDataReset'] = AvdPowerDlg.FirmwareReset; }
            } else {
                // ###END###{PowerControl-Advanced}
                r['BIOSPause'] = false;
                r['EnforceSecureBoot'] = false;
                r['BIOSSetup'] = (action > 99 && action < 104);
                r['BootMediaIndex'] = 0;
                r['FirmwareVerbosity'] = 0;
                r['ForcedProgressEvents'] = false;
                r['IDERBootDevice'] = ((action == 202) || (action == 203))?1:0; // 0 = Boot on Floppy, 1 = Boot on IDER
                r['LockKeyboard'] = false;
                r['LockPowerButton'] = false;
                r['LockResetButton'] = false;
                r['LockSleepButton'] = false;
                r['ReflashBIOS'] = false;
                r['UseIDER'] = ((action > 199) && (action < 300));
                //r['UseSOL'] = ((currentView == 13) && (action != 8) && (action != 300) && (action != 301)); // If we are looking at the terminal, turn on SOL. SOL can't be used with diagnostic mode (300/301)
                r['UseSOL'] = ((currentView == 13) && (action != 8) && (action < 300)); // If we are looking at the terminal, turn on SOL.
                r['UseSafeMode'] = false;
                r['UserPasswordBypass'] = false;
                if (r['SecureErase'] != null) {
                    r['SecureErase'] = (((action == 104) || (action == 105)) && (amtPowerBootCapabilities['SecureErase'] == true));
                    if ((r['SecureErase'] === true) && (rsepass.length > 0)) { r['RSEPassword'] = rsepass; }
                }
                if (r['PlatformErase'] != null) {
                    if ((amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && (amtsysstate['CIM_BootService'].response['EnabledState'] & 2) && (((action == 106) || (action == 107)) && (amtPowerBootCapabilities['PlatformErase'] != null) && (((amtPowerBootCapabilities['PlatformErase'] & 1)) != 0))) {
                        r['PlatformErase'] = true;
                        r['UefiBootParametersArray'] = platfromEraseTLV.tlv;
                        r['UefiBootNumberOfParams'] = platfromEraseTLV.tlvlen;
                    } else {
                        r['PlatformErase'] = false;
                    }
                }
                if (r['ConfigurationDataReset'] != null) { r['ConfigurationDataReset'] = false; }
                rsepass = null;
                // ###BEGIN###{PowerControl-Advanced}
            }

            // ###BEGIN###{PowerControl-OneClick}
            // Add OCR TLV parameters if firmware supports OCR and Force HTTPS Boot is requested
            if ((action == 999) && (Q('idx_d24ForceBootDevice').value == 7)) { // Force UEFI HTTPS Boot using URL
                const bootUrl = new URL(Q('idx_d24ocrBootUrl').value.trim());
                const bootUrlUsername = bootUrl.username;
                const bootUrlPassword = bootUrl.password;
                bootUrl.username = bootUrl.password = '';
                var uefiParams = makeUefiBootParam(1, bootUrl.href) + makeUefiBootParam(20, 1, 1) + makeUefiBootParam(30, 0, 2);
                if (bootUrlUsername != '') { uefiParams += makeUefiBootParam(40, bootUrlUsername); } // HTTP basic auth username
                if (bootUrlPassword != '') { uefiParams += makeUefiBootParam(41, bootUrlPassword); } // HTTP basic auth password
                if (amtversion > 16) {
                    var timeout = parseInt(Q('idx_d24ocrBootHttpBootTimeout').value);
                    if (timeout > 0) { uefiParams += makeUefiBootParam(30, timeout, 2); }
                }
                r['UefiBootParametersArray'] = btoa(uefiParams);
                r['UefiBootNumberOfParams'] = 3;
                r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
            } else if ((action == 600) || (action == 601) || ((action == 999) && (Q('idx_d24ForceBootDevice').value == 6))) { // Force UEFI HTTPS Boot
                // Check if using built-in webserver or external webserver
                r['UefiBootParametersArray'] = webserver.lastBootImageArgs.args;
                r['UefiBootNumberOfParams'] = webserver.lastBootImageArgs.argscount;
                r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
            } else if ((action == 999) && (Q('idx_d24ForceBootDevice').value == 5)) {
                var bootstr = AmtOcrPba[Q('idx_d24customBootMediaIndex').value].bootstr;
                console.log('OCR BootStr: ' + bootstr);
                r['UefiBootParametersArray'] = btoa(makeUefiBootParam(2, bootstr) + makeUefiBootParam(3, bootstr.length, 2)); // EFI_DEVICE_PATH (2) + EFI_DEVICE_PATH-LENGTH (3)
                r['UefiBootNumberOfParams'] = 2;
                r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
            }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}

            //if (((action == 104) || (action == 105)) && !r['SecureErase']) { /*console.log("This Intel&reg; AMT does not support Secure Erase");*/ cleanup(); return; }
            console.log("Azione di avvio: " + action);
            console.log("Impostazione delle impostazioni di avvio: " + ObjectToString2(r));
            statusbox("Azione di potere", "Impostazione delle impostazioni di avvio ...");

            // Set the boot order to null, this is needed for some AMT versions that don't clear this automatically.
            amtstack.CIM_BootConfigSetting_ChangeBootOrder(null, function (stack, name, response, status) {
                if (status != 200) { messagebox("Azione di potere", format("PUT CIM_BootConfigSetting_ChangeBootOrder, Error #{0}", status) + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); return; }
                if (response.Body['ReturnValue'] != 0) { messagebox("Change Boot Order", "(1) Change Boot Order returns "+ response.Body.ReturnValueStr); return; }
                amtstack.Put('AMT_BootSettingData', r, powerActionResponse2, 0, 1);
            }, 0, 1);
        }

        function powerActionResponse2(stack, name, response, status, tag) {
            //console.log("powerActionResponse2(" + name + "," + response + "," + status + ")");
            if (status != 200) { messagebox("Azione di potere", format("PUT AMT_BootSettingData, Errore # {0}", status) + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); return; }
            //if (status == 408) { messagebox("Power Action", "Access denied."); return; }
            //if (errcheck(status, stack)) return;
            //console.log("Setup next boot...");
            statusbox("Azione di potere", "Impostazione del prossimo avvio ...");
            amtstack.SetBootConfigRole(1, powerActionResponse3x, 0, 1);
        }

        function powerActionResponse3x(stack, name, response, status) {
            //console.log("powerActionResponse3x(" + name + "," + response + "," + status + ")");
            var action = d5actionSelect.value, bootSource = null;
            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) {
                // ###BEGIN###{!PowerControl-OneClick}
                if (idx_d24ForceBootDevice.value > 0) { bootSource = ['Force CD/DVD Boot', 'Force PXE Boot', 'Force Hard-drive Boot', 'Force Diagnostic Boot'][idx_d24ForceBootDevice.value - 1]; }
                // ###END###{!PowerControl-OneClick}
                // ###BEGIN###{PowerControl-OneClick}
                if (idx_d24ForceBootDevice.value > 0) { bootSource = ['Force CD/DVD Boot', 'Force PXE Boot', 'Force Hard-drive Boot', 'Force Diagnostic Boot', 'Force OCR UEFI Boot Option ' + Q('idx_d24customBootMediaIndex').value, 'Force OCR UEFI HTTPS Boot', 'Force OCR UEFI HTTPS Boot'][idx_d24ForceBootDevice.value - 1]; }
                // ###END###{PowerControl-OneClick}
            } else {
            // ###END###{PowerControl-Advanced}
                if (action == 300 || action == 301) { bootSource = 'Force Diagnostic Boot'; }
                if (action == 400 || action == 401) { bootSource = 'Force PXE Boot'; }
            // ###BEGIN###{PowerControl-Advanced}
                if (action == 600 || action == 601) { bootSource = 'Force OCR UEFI HTTPS Boot'; }
            }

            // Resetting Force boot data in case it was changed so that it won't be used on the next power action
            Q('idx_d24ForceBootDevice').value = 0;

            // ###END###{PowerControl-Advanced}
            console.log('ChangeBootOrder: ' + bootSource);
            amtstack.CIM_BootConfigSetting_ChangeBootOrder((bootSource == null)?bootSource:'<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BootSourceSetting</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">Intel(r) AMT: ' + bootSource + '</Selector></SelectorSet></ReferenceParameters>', powerActionResponse3);
        }

        var targetPowerAction = 0;
        function powerActionResponse3(stack, name, response, status) {
            //console.log('powerActionResponse3(' + name + ',' + response + ',' + status + ')');
            if (errcheck(status, stack)) return;
            if (response.Body['ReturnValue'] != 0) { messagebox("Change Boot Order", "(2) Change Boot Order returns "+ response.Body.ReturnValueStr); return; }

            //console.log("Performing Power State Change...");
            statusbox("Azione di potere", "Esecuzione dell'azione di potenza ...");
            var action = d5actionSelect.value;
            if (action == 100 || action == 201 || action == 203 || action == 300 || action == 401 || action == 601) action = 2; // Power up
            if (action == 101 || action == 200 || action == 202 || action == 301 || action == 400 || action == 600) action = 10; // Reset
            if (action == 104) action = 2; // Power on with Remote Secure Erase
            if (action == 105) action = 10; // Reset with Remote Secure Erase
            if (action == 106) action = 2; // Power on with Remote Platfrom Erase
            if (action == 107) action = 10; // Reset with Remote Platfrom Erase
            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) action = AvdPowerDlg.Action;
            targetPowerAction = action;
            //console.log('RequestPowerStateChange:' + action);
            if (action == 11) { action = 10; }
            if (action < 999) { console.log('RequestPowerStateChange(' + action + ')'); amtstack.RequestPowerStateChange(action, powerActionResponse4); } else { messagebox("Azione di potere", "Prossimo set di azioni di avvio."); }
            // ###END###{PowerControl-Advanced}
            // ###BEGIN###{!PowerControl-Advanced}
            targetPowerAction = action;
            amtstack.RequestPowerStateChange(action, powerActionResponse4);
            // ###END###{!PowerControl-Advanced}
        }

        function powerActionResponse4(stack, name, response, status) {
            //console.log("powerActionResponse4(" + name + "," + response + "," + status + ")");
            if (status == 200) {
                // Done!
                //console.log("Action Completed.");
                QH('id_dialogMessage', "Azione di potenza completata.");
                setDialogMode(1, "Azione di potere", 0);
                setTimeout(function() { setDialogMode(0); }, 1300);
            }
            // console.log("Power State Error: " + status);
            // Sometimes Intel AMT with not respond and this will timeout. Try to pull the power state
            amtstack.Get('CIM_AssociatedPowerManagementService', powerActionResponse5, 0, 1);
        }

        function powerActionResponse5(stack, name, response, status) {
            //console.log("powerActionResponse5(" + name + "," + response + "," + status + ")");
            /*
            if (errcheck(status, stack)) return;
            var powerstate = parseInt(response.Body['PowerState']);
            console.log("powerstate: " + powerstate);
            if (targetPowerAction == powerstate) {
                console.log("Action Completed. ");
            } else {
                console.log("Power State Error: " + status + ", CurrentState=" + powerstate + ", TargetState=" + targetPowerAction);
            }
            */
        }

        function consentChanged() { QE('idx_dlgOkButton', d6ConsentText.value.length == 6); }
        function changeConsentDisplay() { xxchangeConsentDisplay = true; checkConsentDisplay(); }
        function checkConsentDisplay() { /*console.log("Getting display information...");*/ amtstack.Get('IPS_SecIOService', checkConsentDisplayResponse1); }

        var xxchangeConsentDisplay = false;
        function checkConsentDisplayResponse1(stack, name, response, status) {
            // console.log('checkConsentDisplayResponse1(' + name + ',' + response + ',' + status + ')');
            if (status == 200) {
                if (response.Body['DefaultScreen']) response.Body['DefaultScreen'] = parseInt(response.Body['DefaultScreen']);
                if (response.Body['NumberOfScreens']) response.Body['NumberOfScreens'] = parseInt(response.Body['NumberOfScreens']);
                if (xxchangeConsentDisplay == true) {
                    xxchangeConsentDisplay = false;
                    // Change consent screen settings
                    response.Body['DefaultScreen'] = d6Display.value;
                    amtstack.Put('IPS_SecIOService', response.Body, checkConsentDisplayResponse1);
                } else {
                    d6Display.value = response.Body['DefaultScreen'];
                    QV('d6ThirdDisplay', response.Body['NumberOfScreens'] > 2);
                }
            } else {
                //console.log("Display Error: " + status);
            }
        }

// ###END###{PowerControl}

// ###BEGIN###{Storage}

        //
        // Storage
        //

        var xxStorage = null;
        var xxStorageVendors = [];
        var xxStorageApplications = [];

        function PullStorage() {
            amtFirstPull |= 8;
            wsstack.comm.PerformAjax('', PullStorageResponse, null, 0, '/amt-storage/', 'GET');
        }

        function PullStorageResponse(data, status, tag) {
            if (amtstack.PendingBatchOperations == 0) refreshButtons(true); // If nothing is being done, re-enable refresh buttons
            
            if (status == 200) {
                QV('go21', true); // Show Storage Panel

                var len; // Remove all chars that are below 32, this will allow parsing even the the firmware gives us garbage.
                for (var i = 0; i < 32; i++) { do { len = data.length; data = data.replace(String.fromCharCode(i), ''); } while (len > data.length); }
                //data = '{"information": {"version": 1.1,"realms": 7765759,"user": "admin"},"content": [{"name": "index.htm","size": 38864},{"vendor": "User","app": "SDK","name": "Sample.html","size": 26760,"link": "SDK Sample"},{"vendor": "User","app": "SDK","name": "ws.js","size": 42575,"link": "SDK Sample"},{"vendor": "User","app": "SDK","name": "btp.min.css","size": 121265,"link": "SDK Sample"},{"vendor": "User","app": "SDK","name": "logo.png","size": 2803,"link": "SDK Sample"}]}';
                try { xxStorage = JSON.parse(data); } catch (e) { return; }
                xxStorageVendors = [];
                xxStorageApplications = [];
                var content = xxStorage['content'];

                if (Array.isArray(content)) {
                    // New flat format, convert to tree format.
                    var newcontent = {};
                    for (var i in content) {
                        var vendor = content[i]['vendor'] ? content[i]['vendor'] : '';
                        if (!newcontent[vendor]) { newcontent[vendor] = {}; }
                        var app = content[i]['app'] ? content[i]['app'] : '';
                        if (!newcontent[vendor][app]) { newcontent[vendor][app] = {}; }
                        if (content[i]['name']) { newcontent[vendor][app][content[i]['name']] = content[i]; }
                    }
                    xxStorage['content'] = content = newcontent;
                } else {
                    // Tree format, move index.htm and logon.htm
                    if (content['index.htm'] || content['logon.htm']) { content[''] = { '': {} }; }
                    if (content['index.htm']) { content['']['']['index.htm'] = content['index.htm']; delete content['index.htm']; }
                    if (content['logon.htm']) { content['']['']['logon.htm'] = content['logon.htm']; delete content['logon.htm']; }
                }

                // Display all storage files
                var count = 0, x = TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gestisci lo storage Intel&reg; AMT per questo computer." + '<br><br>';
                var ii, jj, xx = '', links = '', linkid = 30;
                for (var i in content) {
                    var jcount = 0;
                    for (var j in content[i]) {
                        jcount++;
                        var kcount = 0;
                        for (var k in content[i][j]) {
                            kcount++;
                            if (i != ii || j != jj) {
                                if (xx != '') { x += xx; xx = '<br>'; }
                                ii = i; jj = j;
                                if (i != '') { xx += EscapeHtml(i + ' / ' + j); } else { xx += "Radice"; }
                            }
                            //var handle = "\"" + i + "\",\"" + j + "\",\"" + k + "\"";
                            var handle = '\"' + i + ((i != '') ? '/' : '') + j + ((j != '') ? '/' : '') + k + '\"';
                            xx += '<div class=itemBar onclick=showStorageDetails("' + i + '","' + j + '","' + k + '",' + handle + ')><div style=float:right>';
                            // ###BEGIN###{Mode-Firmware}
                            xx += AddButton2("Aperto", 'OpenFromStorage(' + handle + ',event)');
                            // ###END###{Mode-Firmware}
                            // ###BEGIN###{Mode-LMS}
                            xx += ' ' + AddButton2("Aperto", 'OpenFromStorage(' + handle + ',event)');
                            // ###END###{Mode-LMS}
                            // ###BEGIN###{FileSaver}
                            xx += ' ' + AddButton2("Scarica", 'DownloadFromStorage(' + handle + ',\"' + k + '\",event)');
                            // ###END###{FileSaver}
                            xx += '</div><div style=padding-top:3px><b>' + EscapeHtml(k) + '</b>, <i>' + content[i][j][k]['size'] + " byte" + '</i></div></div>';
                            // ###BEGIN###{Mode-Firmware}
                            if (content[i][j][k]['link'] && i != '') { links += '<p id=go' + linkid + ' class=nav1 onclick=goiFrame(event,' + linkid + ',"/amt-storage/' + i + '/' + j + '/' + k + '") title="' + i + ' / ' + j + '"><a>' + content[i][j][k]['link'] + '</a></p>'; linkid++; }
                            // ###END###{Mode-Firmware}
                            count++;
                            if (xxStorageVendors.indexOf(i) == -1) xxStorageVendors.push(i);
                            if (xxStorageApplications.indexOf(j) == -1) xxStorageApplications.push(j);
                        }
                        if (kcount == 0) {  // Clear empty application & vendor
                            wsstack.comm.PerformAjax('', function () { }, null, 0, '/amt-storage/' + i + '/' + j, 'DELETE');
                            wsstack.comm.PerformAjax('', function () { }, null, 0, '/amt-storage/' + i, 'DELETE');
                        }
                    }
                    if (jcount == 0) { wsstack.comm.PerformAjax('', function () { }, null, 0, '/amt-storage/' + i, 'DELETE'); } // Clear empty vendor
                }
                if (xx != '') x += xx;
                if (count == 0) { x += '<div style=padding-left:15px><br><i>' + "Nessun file trovato." + '</i></div><br>'; }
                var uploadSupport = false;
                try { var reader = new FileReader(); uploadSupport = ((reader != null) && (reader.readAsBinaryString != null)); } catch (ex) { console.log(ex); }
                x += '<br><td class=r1>' + TableEnd(AddRefreshButton('PullStorage()') + (uploadSupport ? AddButton("Caricare...", 'UploadToStorage()') : '')
                // ###BEGIN###{Mode-NodeWebkit}
                    //+ AddButton("Upload Application...", 'UploadAppToStorage()')
                // ###END###{Mode-NodeWebkit}
                );
                // ###BEGIN###{Mode-Firmware}
                //QH('storagelinks', links);
                // ###END###{Mode-Firmware}
                QH('id_TableSystemStorage', x);
            } else {
                QH('id_TableSystemStorage', "Impossibile caricare i dati di archiviazione ..." + '<br/>' + AddButton("ricaricare", 'PullStorage()'));
            }
        }

        function showStorageDetails(i, j, k, h) {
            if (xxdialogMode) return;
            var x = '', item = xxStorage['content'][i][j][k];
            if (i != '') x += addHtmlValue("venditore", i);
            if (j != '') x += addHtmlValue("Applicazione", j);
            x += addHtmlValue("Nome", k);
            x += addHtmlValue("Dimensione", item['size'] + ' bytes');
            if (item['link']) { x += addHtmlValue("collegamento", item['link']); }
            setDialogMode(11, "Articolo di archiviazione", 5, showStorageDetailsEx, x, h);
        }

        function showStorageDetailsEx(buttons, handle) {
            if (buttons == 2) { wsstack.comm.PerformAjax('', storageDeleteResponse, null, 0, '/amt-storage/' + handle, 'DELETE'); }
        }

        function storageDeleteResponse(data, status) {
            if (status != 200) {
                messagebox("Conservazione", format("Impossibile eliminare il file (ERR {0}), verificare che il computer sia acceso.", status));
            } else {
                PullStorage();
            }
        }

        // ###BEGIN###{FileSaver}
        function DownloadFromStorage(handle, filename, e) {
            if (xxdialogMode) return;
            haltEvent(e);
            wsstack.comm.PerformAjax('', DownloadFromStorageEx, filename, 0, '/amt-storage/' + handle, 'GET');
        }

        function DownloadFromStorageEx(data, status, tag) {
            if ((status != 200) || (data == null)) { console.log(status, 'Data = null'); return; }
            saveAs(data2blob(data), tag);
        }
        // ###END###{FileSaver}

        function OpenFromStorage(handle, e) {
            if (xxdialogMode) return;
            haltEvent(e);
            // ###BEGIN###{Mode-Firmware}
            var newWindow = window.open('/amt-storage/' + handle, '_blank', 'noopener,noreferrer');
            // ###END###{Mode-Firmware}
            // ###BEGIN###{!Mode-Firmware}
            var newWindow = window.open('http://' + wsstack.comm.host + ':' + wsstack.comm.port + '/amt-storage/' + handle, '_blank', 'noopener,noreferrer');
            // ###END###{!Mode-Firmware}
            newWindow.opener = null;
            newWindow.focus();
        }

        function PushToStorage(vendorAppnameFilename, data, append) {
            var tag = null;
            if (data.length > 7000) { tag = [vendorAppnameFilename, data.substring(7000)]; data = data.substring(0, 7000); }
            wsstack.comm.PerformAjax(data, PushToStorageResponse, tag, 0, '/amt-storage/' + vendorAppnameFilename + (append == true ? '?append=' : ''), 'PUT');
        }

        function PushToStorageResponse(data, status, tag) {
            if (status != 200) { messagebox("Conservazione", format("Impossibile inviare il file (ERR {0}), verificare che il computer sia acceso.", status)); } else {
                if (tag != null) { PushToStorage(tag[0], tag[1], true); } else { PullStorage(); }
            }
        }

        function UploadToStorage(file, filename) {
            if (xxdialogMode) return;
            if (!filename) { filename = ''; }
            var x = '';
            x += '<br>' + "Seleziona un piccolo file da caricare nella memoria e inserisci un fornitore, un'applicazione e un nome file." + '<br>';
            if (!file) {
                x += '<br><div style=height:20px><input type=file id=mstoragefile style=float:right;width:240px onchange=SetStorageName()><div>Upload file</div></div>';
            } else {
                x += '<br><div style=height:20px><input id=mstoragefile style=float:right;width:240px readonly disabled=disabled value="' + filename + '" ><div>' + "Caricare un file" + '</div></div>';
            }
            x += '<br><div style=height:16px><input id=mstoragevendor placeholder="' + "venditore" + '" list=mstoragevendorlist maxlength=11 style=float:right;width:240px><div>' + "Nome del fornitore" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstorageapplication placeholder="' + "App" + '" list=mstorageapplicationlist maxlength=11 style=float:right;width:240px><div>' + "Nome dell'applicazione" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstoragefilename placeholder="' + "Nome del file" + '" maxlength=11 style=float:right;width:240px><div>' + "Nome del file" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstoragetype placeholder=application/octet-stream list=mstoragetypelist style=float:right;width:240px><div>' + "Tipo MIME" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstoragelink style=float:right;width:240px><div title=\"' + "Se impostato, crea un collegamento a questo contenuto dalla pagina Web principale" + '\">' + "collegamento" + '</div></div><br>';
            x += '<datalist id=mstoragevendorlist>';
            for (var i in xxStorageVendors) { x += '<option value="' + xxStorageVendors[i] + '">'; }
            x += '</datalist>';
            x += '<datalist id=mstorageapplicationlist>';
            for (var i in xxStorageApplications) { x += '<option value="' + xxStorageApplications[i] + '">'; }
            x += '</datalist><datalist id=mstoragetypelist><option value="application/octet-stream"><option value="image/jpeg"><option value="text/html"><option value="text/plain"></datalist>';
            setDialogMode(11, "Caricamento archiviazione", 3, UploadToStorageEx, x, file);
            if (file) { SetStorageName(filename); }
        }

        // ###BEGIN###{Mode-NodeWebkit}
        /*
        var UploadAppToStorageFileList;
        function UploadAppToStorage() {
            if (xxdialogMode) return;
            require('fs').readdir('.', function read(err, data) {
                var filelist = [], filecount = 0;
                if (err == null) { for (var i in data) { if ((data[i].endsWith('.gz')) || (data[i].endsWith('.br'))) { filelist.push(data[i]); filecount++; } } }
                if (filecount > 0) {
                    var x = '';
                    x += "Select the web application to upload, this will replace the Intel&reg; AMT default web pages." + '<br><br><div style=height:26px><select id=mwebappsel style=float:right;width:240px>';
                    for (var i in filelist) { x += '<option value=' + i + '>' + filelist[i].substring(0, filelist[i].length - 3) + '</option>'; }
                    x += '</select><div>' + "Web Application" + '</div></div>';
                    setDialogMode(11, "Storage Application Upload", 3, UploadAppToStorageEx, x, filelist);
                }
            });
        }

        function UploadAppToStorageEx(b, filelist) {
            var file = filelist[Q('mwebappsel').value];
            require('fs').readFile(file, 'binary', function read(err, data) {
                if (err == null) { PushToStorage('index.htm', '<metadata><headers><h>Content-Encoding: ' + (file.endsWith('.br')?'br':'gzip') + '</h><h>Content-Type: text/html</h></headers></metadata>' + data); }
            });
        }
        */
        // ###END###{Mode-NodeWebkit}

        function UploadToStorageEx(button, tag) {
            if (!tag) {
                var x = Q('mstoragefile');
                if (x.files.length != 1) return;
                var reader = new FileReader();
                reader.onload = UploadToStorageEx2;
                reader.filename = x.files[0].name;
                reader.readAsBinaryString(x.files[0]);
            } else {
                var reader = new FileReader();
                reader.onload = UploadToStorageEx2;
                reader.filename = Q('mstoragefile').value;
                reader.readAsBinaryString(tag);
            }
        }

        function SetStorageName(filename) {
            if (!filename) {
                var x = Q('mstoragefile');
                if (x.files.length == 1) { filename = x.files[0].name; } else { filename = ''; }
            }
            filename = filename.split(' ').join('');
            var filenameSplit = filename.split('-');
            if (filenameSplit.length == 3 && filenameSplit[0].length < 12 && filenameSplit[1].length < 12) {
                Q('mstoragevendor').value = filenameSplit[0];
                Q('mstorageapplication').value = filenameSplit[1];
                filename = filenameSplit[2];
            }
            filename = filename.split('-').join('');
            if (filename.endsWith('.gz')) filename = filename.substring(0, filename.length - 3);
            if (filename.endsWith('.htm') || filename.endsWith('.html')) Q('mstoragetype').value = 'text/html';
            else if (filename.endsWith('.txt')) Q('mstoragetype').value = 'text/plain';
            if (filename.length > 11) filename = filename.substring(0, 11);
            Q('mstoragefilename').value = filename;
        }

        function UploadToStorageEx2(file) {
            var vaf, vendor = Q('mstoragevendor').value;
            var app = Q('mstorageapplication').value;
            var filename = Q('mstoragefilename').value;
            if (filename == '') filename = 'Filename';
            var mimetype = Q('mstoragetype').value;
            if (mimetype == '') mimetype = 'application/octet-stream';
            var link = Q('mstoragelink').value;
            if (vendor == '' && app == '' && (filename.toLowerCase() == 'logon.htm' || filename.toLowerCase() == 'index.htm')) {
                vaf = filename.toLowerCase();
            } else {
                if (vendor == '') vendor = 'Vendor';
                if (app == '') app = 'App';
                vaf = vendor + '/' + app + '/' + filename;
            }

            var data = '<metadata><headers>';
            var filename = file.target.filename;
            if (!filename) { filename = Q('mstoragefile').files[0].name; }
            if (filename.endsWith('.gz')) { data += '<h>Content-Encoding: gzip</h>'; }
            data += '<h>Content-Type: ' + mimetype + '</h></headers>'; // <h>X-UA-Compatible: IE=Edge</h>
            if (link != '') data += '<link>' + link + '</link>';
            data += '</metadata>' + file.target.result;

            PushToStorage(vaf, data);
        }

// ###END###{Storage}

// ###BEGIN###{Alarms}

        //
        // Alarm Panel
        //

        function _fmtdatetime(str) {
            return str.replace('T',' ').replace('Z','');
        }

        function _fmtinterval(str) {
            var cl = str.replace('T', '').substring(str.indexOf('P') + 1);
            cl = ' ' + cl.replace('D', " giorni").replace('H', " ore").replace('M'," minuti");
            cl = cl.replace(" 1 giorni", " 1 giorno").replace(" 1 ora", " 1 ora").replace(" 1 minuti "," 1 minuto ");
            return cl.substring(0, cl.length - 1);
        }

        function _fmttimepad(str) {
            str = '' + str;
            while (str.length < 2) { str = '0' + str; }
            return str;
        }

        var xxAlarms = null;

        function PullAlarms() {
            var x = TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gestisci sveglie." + '<br><br>';
            amtstack.Enum('IPS_AlarmClockOccurrence', function(stack, name, response, status) {
                if (status == 200) {
                    QV('go23', true);
                    if (response.length > 0) {
                        xxAlarms = response;
                        for (var i = 0; i < response.length; i++) {
                            var waketime = new Date(response[i]['StartTime']['Datetime']);
                            var details = '<b>' + response[i]['ElementName'] + '</b>, ' + "svegliati" + ' ' + waketime.toLocaleString().replace(', ', " a");
                            if (response[i]['Interval'] != undefined) { details += " e ciascuno" + _fmtinterval(response[i]['Interval']['Interval']); }
                            if (response[i]['DeleteOnCompletion'] == true) { details += ", eliminare al termine"; }
                            x += '<div class=itemBar onclick=showAlertDetails(' + i + ')><div style=float:right>';
                            if (xxAccountAdminName) x += ' ' + AddButton2("Modificare...", 'showAddAlarm(" + i + ")');
                            x += '</div><div style=padding-top:3px;width:auto;float:left;overflow-x:hidden>' + details + '</div></div>';
                        }
                    } else {
                        xxAlarms = null;
                        x += '<div style=padding-left:15px><br><i>' + "Nessun allarme di sveglia registrato." + '</i></div><br>';
                    }
                    var y = '<div>&nbsp;' + AddRefreshButton('PullAlarms()');
                    if (xxAccountAdminName) { y += AddButton2("Rimuovi tutti gli allarmi", 'RemoveAllAlarms()', xxAlarms ? '' : 'disabled') + AddButton("Inserisci", 'showAddAlarm()'); }
                    x += '<br><td class=r1>' + TableEnd(y + '</div>');
                    QH('id_TableAlarm', x);
                }
            }, null, true);
        }

        function prepareAlarmOccurenceTemplate(id, nm, start, interval, del) {
            return '<d:AlarmTemplate xmlns:d=\"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AlarmClockService\" xmlns:s=\"http://intel.com/wbem/wscim/1/ips-schema/1/IPS_AlarmClockOccurrence\"><s:InstanceID>' + id + '</s:InstanceID><s:StartTime><p:Datetime xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + start + '</p:Datetime></s:StartTime><s:Interval><p:Interval xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + interval + '</p:Interval></s:Interval><s:DeleteOnCompletion>' + del + '</s:DeleteOnCompletion></d:AlarmTemplate>';
        }
        
        function RemoveAllAlarms(){
            setDialogMode(1, "Rimuovi tutti gli allarmi di riattivazione", 3, RemoveAllAlarmsEx, "Conferma la rimozione di tutti gli allarmi di riattivazione?");
        }

        function RemoveAllAlarmsEx() {
            var deleteCount = xxAlarms.length;
            for (var a in xxAlarms) { amtstack.Delete('IPS_AlarmClockOccurrence', xxAlarms[a], function(stack, name, response, status) { if (--deleteCount == 0) { PullAlarms(); }}); }
        }

        function showAddAlarm(alrm){
            if (xxdialogMode) return;
            QE('d25alarm_name', !alrm);
            if (alrm != undefined) {
                var alarm = xxAlarms[alrm], waketime = new Date(alarm['StartTime']['Datetime']);
                Q('d25alarm_name').value = alarm['ElementName'];
                Q('d25alarm_sdate').value = waketime.getFullYear() + '-' + _fmttimepad(waketime.getMonth() + 1) + '-' + _fmttimepad(waketime.getDate());
                Q('d25alarm_stime').value = waketime.getHours() + ':' + _fmttimepad(waketime.getMinutes()) + ':' + _fmttimepad(waketime.getSeconds());
                if (alarm['Interval']) {
                    var j = alarm['Interval']['Interval'].replace('P','').replace('T','').replace('D','D,').replace('H','H,').replace('M','M,').split(','), k = [0, 0, 0];
                    for (var i in j) {
                        var jl = j[i].length - 1;
                        if (j[i][jl] == 'D') { k[0] = parseInt(j[i].substring(0, jl)); }
                        if (j[i][jl] == 'H') { k[1] = parseInt(j[i].substring(0, jl)); }
                        if (j[i][jl] == 'M') { k[2] = parseInt(j[i].substring(0, jl)); }
                    }
                    Q('d25alarm_interval').value = k.join('-');
                } else {
                    Q('d25alarm_interval').value = '';
                }
                Q('d25alarm_doc').value = (alarm['DeleteOnCompletion'] == true)?1:0;
            } else {
                var currentTime = new Date();
                currentTime.setDate(new Date().getDate() + 1);
                Q('d25alarm_name').value = '';
                Q('d25alarm_sdate').value = currentTime.getFullYear() + '-' + _fmttimepad(currentTime.getMonth() + 1) + '-' + _fmttimepad(currentTime.getDate());
                Q('d25alarm_stime').value = currentTime.getHours() + ':' + _fmttimepad(currentTime.getMinutes()) + ':00';
                Q('d25alarm_interval').value = '';
                Q('d25alarm_doc').value = 0;
            }
            setDialogMode(25, "Aggiungi nuova sveglia", (alrm != undefined)?7:3, showAddAlarmOk, '', alrm);
            alertDialogUpdate();
        }

        function alertDialogUpdate() {
            var il = Q('d25alarm_interval').value.split('-').length;
            var ok = (Q('d25alarm_name').value.length > 0) && (Q('d25alarm_sdate').value.split('-').length == 3) && (Q('d25alarm_stime').value.split(':').length == 3) && ((il == 1) || (il == 3));
            QE('idx_dlgOkButton', ok);
        }

        function showAddAlarmOk(button, alrm) {
            if (button == 2) { showAlertDetailsDelete(button, alrm); return; }
            var alarm_name = Q('d25alarm_name').value;
            var x1 = Q('d25alarm_sdate').value.split('-');
            var x2 = Q('d25alarm_stime').value.split(':');
            var t = new Date(x1[0], x1[1] - 1, x1[2], x2[0], x2[1], x2[2], 0); // Month is 0 = JAN, 11 = DEC
            var alarm_starttime = _fmttimepad(t.getUTCFullYear()) + '-' + _fmttimepad(t.getUTCMonth() + 1) + '-' + _fmttimepad(t.getUTCDate()) + 'T' + _fmttimepad(t.getUTCHours()) + ':' + _fmttimepad(t.getUTCMinutes()) + ':' + _fmttimepad(t.getUTCSeconds()) + 'Z';
            var x = Q('d25alarm_interval').value.split('-');
            if (x.length != 3) { x = [0, 0, 0]; }
            var alarm_interval = 'P' + x[0] + 'DT' + x[1] + 'H' + x[2] + 'M';
            var alarm_doc = (Q('d25alarm_doc').value == 1);
            var tpl = prepareAlarmOccurenceTemplate(alarm_name, alarm_name, alarm_starttime, alarm_interval, alarm_doc);
            if (alrm == undefined) {
                wsstack.ExecMethodXml(amtstack.CompleteName('AMT_AlarmClockService'), 'AddAlarm', tpl,
                    function (ws, resuri, response, status) {
                        if (status != 200) { messagebox("Aggiungi allarme", format("Impossibile aggiungere l'allarme. Stato: {0}. <br/> Verifica che l'allarme sia per un momento futuro.", status)); return; }
                        if (response.Body['ReturnValue'] != 0) { messagebox("Aggiungi allarme", format("Impossibile aggiungere la sveglia {0}. <br/> Verifica che la sveglia sia per un momento futuro.", response.Body['ReturnValueStr'])); return; }
                        PullAlarms();
                    }
                );
            } else {
                var alarmx = Clone(xxAlarms[alrm]);
                alarmx['StartTime'] = '<p:Datetime xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + alarm_starttime + '</p:Datetime>';
                alarmx['Interval'] = '<p:Interval xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + alarm_interval + '</p:Interval>';
                alarmx['DeleteOnCompletion'] = alarm_doc;
                amtstack.Put('IPS_AlarmClockOccurrence', alarmx, function (ws, resuri, response, status) {
                    if (status != 200) { messagebox("Modifica sveglia", format('Failed to change alarm. Status: {0}.<br/>Verify the alarm for at a future time.', status)); return; }
                    PullAlarms();
                }, null, null, { 'InstanceID' : alarmx['InstanceID']});
            }
        }

        function showAlertDetails(i) {
            if (xxdialogMode) return;
            var alarm = xxAlarms[i], waketime = new Date(alarm['StartTime']['Datetime']);
            var x = '<div style=text-align:left>' + addHtmlValue("Nome", alarm['ElementName']) + addHtmlValue("Tempo di sveglia", waketime.toLocaleString().replace(', ', ' at '));
            if (alarm['Interval'] != undefined) { x += addHtmlValue("Interno", _fmtinterval(alarm['Interval']['Interval'])); }
            x += addHtmlValue("Dopo la veglia", (alarm['DeleteOnCompletion'] == true)?"Elimina allarme":"Mantieni allarme") + '</div>';
            messagebox(format("Allarme {0}", alarm['ElementName']), x);
            setDialogMode(11, "Allarme" + alarm['ElementName'], 5, showAlertDetailsDelete, x, i);
        }

        function showAlertDetailsDelete(button, tag) {
            if (button == 2) { amtstack.Delete('IPS_AlarmClockOccurrence', xxAlarms[tag], function(stack, name, response, status) { PullAlarms(); }); }
        }

// ###END###{Alarms}

// ###BEGIN###{Scripting}

        //
        // Scripting
        //

        // Called by the "Run Script..." button. Display a dialog box to ask for the script file.
        function script_runScriptDlg() {
            if (xxdialogMode || scriptstate) return;
            setDialogMode(11, "Esegui script", 3, script_runScriptDlgOk, '<br><input id=scriptopen type=file style=width:100% accept=.mescript>');
        }

        // Once the script file is selected, decode the script here.
        function script_runScriptDlgOk(r) {
            if (r != 1) return;
            var x = Q('scriptopen');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = script_onScriptRead;
            reader.readAsBinaryString(x.files[0]);
        }

        // Called once the script is decoded, get the script setup and start running it.
        function script_onScriptRead(file) {
            var x;
            try { x = JSON.parse(file.target.result); } catch (e) {}
            // ###BEGIN###{Scripting-Editor}
            if (currentView == 20) {
                // Load script into editor
                if (x['scriptText']) Q('scriptarea').value = x['scriptText'];
                if (x['mescript']) Q('compiledarea').value = rstr2hex(atob(x['mescript']));
                if (x['blocks']) { script_setBuildBlocks(x['blocks']); scriptViewButton(1); } else { script_setBuildBlocks(); scriptViewButton(0); }
                if (x['scriptBlocks']) { script_BlockScript = x['scriptBlocks']; } else { if (!script_BuildingBlocks) { script_BlockScript = []; } }

                // Update the scriptBlocks to the latest blocks. This is does because we may update an existing script to new blocks.
                for (var i in script_BlockScript) {
                    var block = script_BlockScript[i];
                    var xblock = script_BuildingBlocks[block['xname']];
                    if (xblock) {
                        var b = Clone(xblock); // Clone a new block, then set all the variables.
                        b['id'] = block['id'];
                        b['xname'] = block['xname'];
                        for (var j in b.vars) { if (block.vars[j]) { b.vars[j]['value'] = block.vars[j]['value']; } }
                        script_BlockScript[i] = b;
                    }
                }

                // Reset the script state
                fupdatescript();
                delete scriptstate;
                resetScriptButton();
                return;
            }
            // ###END###{Scripting-Editor}
            var startvars = { '_interactive':1 };
            // ###BEGIN###{Certificates}
            startvars['_certificates'] = 1;
            // ###END###{Certificates}
            // ###BEGIN###{!Mode-Firmware}
            startvars['_mode'] = 'Firmware';
            // ###END###{!Mode-Firmware}
            // ###BEGIN###{!Mode-MeshCentral2}
            startvars['_mode'] = 'MeshCentral2';
            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            startvars['_mode'] = 'NodeWebkit';
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Mode-LMS}
            startvars['_mode'] = 'LMS';
            // ###END###{Mode-LMS}
            // ###BEGIN###{Mode-WebSite}
            startvars['_mode'] = 'WebSite';
            // ###END###{Mode-WebSite}
            if (x && x['mescript']) scriptstate = script_setup(atob(x['mescript']), startvars);
            if (scriptstate) {
                scriptstate.wsstack = wsstack;
                scriptstate.amtstack = amtstack;
                scriptstate.onStep = script_updateScriptState;
                scriptstate.onConsole = script_console;
                scriptstate.start(100);
            } else {
                messagebox("Esegui script", "File di script non valido.");
            }
        }

        // Called when the script changes state, displays the green status bar at the top of the web page.
        function script_updateScriptState() {
            if (scriptstate) {
                QV('id_scriptstatus', scriptstate.state > 0); center();
                if (scriptstate.state == 0) {
                    // ###BEGIN###{Mode-NodeWebkit}
                    if (urlvars['autoexit']) { // Exit if script finished running
                        require('nw.gui').Window.get().close();
                        //require('nw.gui').App.quit();
                        return;
                    }
                    // ###END###{Mode-NodeWebkit}
                    scriptstate = undefined;
                }
            }
        }

        // Called by a running script to update the console. The last message in the console is displayed in the top green bar.
        function script_console(msg) {
            if (msg.indexOf('INFO: ') == 0) { msg = msg.substring(6); }
            if (msg.indexOf('SUCCESS: ') == 0) { msg = msg.substring(9); }
            if (msg.indexOf('ERROR: ') == 0) { msg = msg.substring(7); }
            QH('id_scriptstatusstr', ', ' + msg);
        }

        // Called by the "Stop" button on the script status bar. Causes the script to stop.
        function script_Stop() {
            if (scriptstate) {
                if (scriptstate.dialog == true) { setDialogMode(0); }
                scriptstate.stop();
                scriptstate.state = 0;
                script_updateScriptState();
            }
        }

// ###END###{Scripting}

// ###BEGIN###{Scripting-Editor}
        
        var script_BuildingBlocks; // List of block that can be used to build a script. This is shown on the list side.
        var script_StartingBuildingBlocks; // List of block that can be used to build a script when you get started.
        var script_BlockScript = []; // List of blocks that are part of the current script.
        var script_BlockScriptSelectedId = null; // The identifier of the currently selected block.
        var script_BuilderView = 0; // 0 = Editor View, 1 = Builder View
        var editscriptstate; // This is the instance of the script runner used by the editor. This is different from the runner used by the web page.

        // ###BEGIN###{!Mode-Firmware}
        function scriptLoadStartingBlocks() {
            // ###BEGIN###{!Mode-NodeWebkit}
            var request = new XMLHttpRequest();
            request.onload = function() {
                if (request.status >= 200 && request.status < 400) {
                    // Success
                    var x;
                    try { x = JSON.parse(request.responseText); } catch (e) {}
                    if ((x) && (x['blocks'])) { script_StartingBuildingBlocks = x['blocks']; script_setBuildBlocks(script_StartingBuildingBlocks); }
                }
            };
            request.onerror = function() { console.log('Failed to get script blocks'); };
            request.open('GET', 'scriptblocks.txt', true);
            request.send();
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var content;
            require('fs').readFile('scriptblocks.txt', 'utf8', function read(err, data) {
                if (err == null) {
                    var x;
                    try { x = JSON.parse(data); } catch (e) {}
                    if (x['blocks']) { script_StartingBuildingBlocks = x['blocks']; script_setBuildBlocks(script_StartingBuildingBlocks); }
                }
            });
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{!Mode-Firmware}

        // Called by the "View Editor" or "View Builder" button to toggle between the view modes.
        // If there is no construction blocks, display the script editor only.
        function scriptViewButton(x) {
            script_BuilderView = x;
            QV('scripteditor', x == 0);
            QV('scriptbuilder', x == 1);
            QV('viewEditorButton', script_BuildingBlocks && (x == 1));
            QV('viewBuilderButton', script_BuildingBlocks && (x == 0));
        }

        // Display the list of construction script block on the left side.
        function script_setBuildBlocks(blocks) {
            script_BuildingBlocks = blocks;
            var x = '';
            if (blocks) {
                for (var i in blocks) {
                    if (i.charCodeAt(0) != 95) {
                        x += '<div id=sblock_' + i + ' style=cursor:pointer;background-color:#ccc;width:auto;padding:5px;margin:2px ondblclick=script_faddblock("' + i + '") draggable=true ondragstart=script_fondragstart(event,this) ondragend=script_fondragend(event,this) title="' + blocks[i]['desc'] + '"';
                        // ###BEGIN###{ContextMenus}
                        var cmenus = [];
                        cmenus.push("Inserisci" + '#script_faddblock("' + i + '")');
                        cmenus.push("Modificare..." + '#script_feditblock("' + i + '")');
                        x += ' cm=\"' + cmenus.join('|') + '\"';
                        // ###END###{ContextMenus}
                        x += '>' + blocks[i]['name'] + '</div>';
                    }
                }
            }
            QH('blocks', x);
            script_fonfilterchanged();
            scriptViewButton(script_BuildingBlocks?1:0);
        }

        // Add a new block to the end of the block script. This is called when you right click on a block and hit "Add" in the context menu.
        function script_faddblock(h) {
            var b = Clone(script_BuildingBlocks[h]); // To add a new block to the script, clone the block, assign it a random id and set the xname to the name of the block.
            b['id'] = Math.random();
            b['xname'] = h;
            script_BlockScript.push(b); // Now that a block is created, add it at the end of the script and set it as the selected block.
            script_BlockScriptSelectedId = script_BlockScript.length - 1;
            fupdatescript(); // Re-display the list of script blocks. The selected block will also be highlighted.
        }

        // Edit a script block
        function script_feditblock(h) {
            if (xxdialogMode) return;
            setDialogMode(11, format("Modifica {0}", script_BuildingBlocks[h]['name']), 3, script_feditblockEx, 'Edit this block? This operation will reset the block editor and load the block code into the code editor.', h);
        }

        // Called when the script block edit dialog is closed.
        function script_feditblockEx(button, h) {
            script_newScriptDlgOk();
            scriptViewButton(0);
            var x = '', b = script_BuildingBlocks[h];
            x += '##!BLOCK!##\r\n#id=' + h + '\r\n#name=' + b['name'] + '\r\n#desc=' + b['desc'] + '\r\n##!BLOCK!##\r\n';
            for (var i in b['vars']) {
                var v = b['vars'][i];
                x += '##!VAR!##\r\n#id=' + i + '\r\n#name=' + v['name'] + '\r\n#desc=' + v['desc'] + '\r\n#type=' + v['type'] + '\r\n';
                if (v['maxlength']) { x += '#maxlength=' + v['maxlength'] + '\r\n'; }
                if (v['values']) { for (var j in v['values']) { x += '#values-' + j +'=' + v['values'][j] + '\r\n'; } }
                x += '#value=' + v['value'] + '\r\n##SWAP %%%' + i + '%%% ' + v['value'] + '\r\n';
            }
            x += '##!VAR!##\r\n##SWAP %%%~%%% 0\r\n\r\n##!BLOCK!##\r\n' + b['code'] + '\r\n##!BLOCK!##\r\n';
            Q('scriptarea').value = x;
        }

        function script_fConvertScriptToJsonBlock(script) {
            var result = {}, scriptparts = script.split('##!BLOCK!##\n'), scriptlines = scriptparts[1].split('\n');

            // Parse information part
            for (var i in scriptlines) {
                var s = scriptlines[i].split('=');
                if (s.length == 2) { result[s[0].substring(1)] = s[1]; }
            }

            // Parse variables part
            result['vars'] = {};
            scriptvariables = scriptparts[2].split('##!VAR!##\n');
            for (var i in scriptvariables) {
                scriptlines = scriptvariables[i].split('\n');
                var v = {}, values = {}, valueslen = 0;
                for (var j in scriptlines) {
                    var s = scriptlines[j].split('=');
                    if ((s.length == 2) && (s[1])) {
                        if ((s[0]) && (s[0].length > 0)) {
                            if (s[0].substring(0, 8) == '#values-') {
                                values[s[0].substring(8)] = s[1];
                                valueslen++;
                            } else {
                                v[s[0].substring(1)] = s[1];
                            }
                        }
                    }
                }
                if (v.id) {
                    if (valueslen > 0) { v['values'] = values; }
                    var id = v.id;
                    delete v.id;
                    result['vars'][id] = v;
                }
            }

            // Parse code part
            result['code'] = scriptparts[3];

            // Package the result
            var id = result.id;
            delete result.id;
            var r = {};
            r[id] = result;
            return JSON.stringify(r, null, '  ');
        }

        /*
        // If the delete key is pressed, delete the block
        function script_fonkeypress(e) {
            if (xxdialogMode) return;
            if (e.key == 'Delete' && script_BlockScriptSelectedId != null) {
                //delete script_BlockScript[script_BlockScriptSelectedId];
                script_BlockScript.splice(script_BlockScriptSelectedId, 1);
                script_BlockScriptSelectedId = null;
                fupdatescript();
            }
        }
        */

        // Filer the list of blocks on the left side list.
        function script_fonfilterchanged() {
            var filter = Q('blockfilter').value.toLowerCase();
            for (var i in script_BuildingBlocks) {
                // Script blocks that start with "_" are hidden blocks and should never be shown.
                if (i.charCodeAt(0) != 95) { QV('sblock_' + i, (script_BuildingBlocks[i]['name'].toLowerCase().indexOf(filter) >= 0 || script_BuildingBlocks[i]['desc'].toLowerCase().indexOf(filter) >= 0)); }
            }
        }

        // Called when you click on a block. If you double click, on a block, do like pressing on the "Edit..." button.
        var script_fonclickDblClickDetectIndex = null;
        var script_fonclickDblClickDetectTime = null;
        function script_fonclick(e, t) {
            // ###BEGIN###{ContextMenus}
            hideContextMenu(); // Any click on this area must close the context menu
            // ###END###{ContextMenus}
            if (xxdialogMode) return;
            script_BlockScriptSelectedId = null;
            if (t) { t = fgetParentWithId(t); if (t.id.startsWith('xblock_')) { script_BlockScriptSelectedId = t.id.substring(7); } } // Figure out what block was clicked on
            fupdatescript(); // This will show the currently selected block in a different color.
            haltEvent(e);

            // Figure out if this is a double click. We need two clicks on the same object within 250ms.
            if (script_fonclickDblClickDetectIndex == script_BlockScriptSelectedId && (new Date().getTime() - script_fonclickDblClickDetectTime) < 250) { return script_foneditclick(script_BlockScriptSelectedId); }
            script_fonclickDblClickDetectIndex = script_BlockScriptSelectedId;
            script_fonclickDblClickDetectTime = new Date().getTime();
        }

        // Script block drag & drop functions, allow the user to create and move script blocks.
        function script_fondragstart(e, t) { if (xxdialogMode) return; t = fgetParentWithId(t); t.style.opacity = '0.4'; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('scriptbuilder/block', t.id); }
        function script_fondragend(e, t)   { if (xxdialogMode) return; t = fgetParentWithId(t); t.style.opacity = '1.0'; }
        function script_fondragenter(e, t) { if (xxdialogMode) return; fgetParentWithId(t).style['border-top'] = 'solid 2px black'; }
        function script_fondragleave(e, t) { if (xxdialogMode) return; e = e.originalEvent || e; var currentElement = document.elementFromPoint(e.pageX, e.pageY); if (!t.contains(currentElement)) { fgetParentWithId(t).style['border-top'] = 'none'; } }

        // Called when you drop a block on the block script area. This code will add or move a block into it's new place.
        function script_fondrop(e, t) {
            if (xxdialogMode) return;
            t = fgetParentWithId(t);
            var b, x = e.dataTransfer.getData('scriptbuilder/block'), dp = parseInt(t.id.substring(7));
            if (x == '') { documentFileSelectHandler(e); return; }
            if (x.startsWith("sblock_")) {
                // Create a new script block
                b = Clone(script_BuildingBlocks[x.substring(7)]);
                b['id'] = Math.random();
                b['xname'] = x.substring(7);
            } else {
                // Pull an existing script block from the list
                var i = parseInt(x.substring(7));
                b = script_BlockScript[i];
                script_BlockScript.splice(i, 1);
                if (dp > i) dp--;
            }
            if (t.id == 'scriptblocks') {
                // Put the block at the end of the list
                if (b) script_BlockScript.push(b);
                script_BlockScriptSelectedId = script_BlockScript.length - 1;
            } else {
                // Insert the block within the list, above the drop point
                script_BlockScript.splice(dp, 0, b);
                script_BlockScriptSelectedId = dp;
            }
            fupdatescript();
            haltEvent(e);
        }

        // Called when you hit "Edit..." on a block, displays a dialog box with all block attributes.
        function script_foneditclick(h) {
            if (xxdialogMode) return;
            var block = script_BlockScript[h];
            script_BlockScriptSelectedId = h;
            fupdatescript();

            if (block != null) {
                var b = block['vars'] ? 7 : 5;
                var c = block['desc'] + '<br><br>';
                if (block['vars']) {
                    // For each variable in a block, add the proper input control for this variable and set the control to the current value.
                    for (var i in block['vars']) {
                        var d = block['vars'][i]['value'];
                        var attributes = '';
                        // Block values can be on type 1:Text,2:Number,3:DropDownList,4:password,5:MultiSelect
                        if (block['vars'][i]['maxlength']) attributes += (' maxlength=' + block['vars'][i]['maxlength']);
                        if (block['vars'][i]['type'] == 2) { attributes += ' onkeypress=\'return numbersOnly(event)\'' }
                        if (block['vars'][i]['type'] == 1 || block['vars'][i]['type'] == 2) { d = '<input title="' + block['vars'][i]['desc'] + '" id=scriptXvalue_' + i + ' value="' + block['vars'][i]['value'] + '" ' + attributes + ' style=width:100%></input>'; }
                        if (block['vars'][i]['type'] == 3) {
                            d = '<select title=\'' + block['vars'][i]['desc'] + '\' id=scriptXvalue_' + i + ' style=width:100%;padding:0;margin:0>';
                            for (var j in block['vars'][i]['values']) { d += '<option value=' + j + (j == block['vars'][i]['value'] ? ' selected' : '') + '>' + block['vars'][i]['values'][j] + '</option>'; }
                            d += '</select>';
                        }
                        if (block['vars'][i]['type'] == 4) { d = '<input type=password autocomplete=off title="' + block['vars'][i]['desc'] + '" id=scriptXvalue_' + i + ' value="' + block['vars'][i]['value'] + '" ' + attributes + ' style=width:100%></input>'; }
                        if (block['vars'][i]['type'] == 5) { d = ''; }
                        if (block['vars'][i]['type'] == 6) { d = '<input type=file title="' + block['vars'][i]['desc'] + '" id=scriptXvalue_' + i + ' ' + attributes + ' style=width:100%></input>'; }
                        c += '<table style=width:100% title="' + block['vars'][i]['desc'] + '"><td style=width:120px>' + block['vars'][i]['name'] + '<td><b>' + d + '</b></table>';
                        if (block['vars'][i]['type'] == 5) {
                            var x = '';
                            c += '<ul id=scriptXvalue_' + i + ' style="list-style-type:none;height:100px;overflow:auto;width:100%;border:1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0">';
                            for (var y in block['vars'][i]['values']) {
                                var xc = '';
                                if (block['vars'][i]['value'].indexOf(y) >= 0) xc = ' checked';
                                c += '<li><label><input type=checkbox id=scriptXvaluex_' + i + '-' + y + '' + xc + '>' + block['vars'][i]['values'][y] + '</label></li>';
                            }
                            c += '</ul>';
                        }
                    }
                }
            }

            // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 11 only)
            setDialogMode(11, block.name, b, script_foneditclickEx, c, h);
        }

        // Called when the script block edit dialog is closed.
        function script_foneditclickEx(button, tag) {
            if (xxdialogMode) return;
            if (button == 2) {
                // Delete this block
                script_BlockScript.splice(tag, 1);
                if (script_BlockScriptSelectedId == tag) { script_BlockScriptSelectedId = null; }
            } else {
                // Change this block with new arguments
                var block = script_BlockScript[tag];
                if (block['vars']) {
                    for (var i in block['vars']) {
                        if (block['vars'][i]['type'] == 5) {
                            block['vars'][i]['value'] = [];
                            for (var y in block['vars'][i]['values']) { if (Q('scriptXvaluex_' + i + '-' + y).checked) block['vars'][i]['value'].push(y); }
                        } else if (block['vars'][i]['type'] == 6) {
                            var x = Q('scriptXvalue_' + i);
                            if (x.files.length == 1) {
                                var reader = new FileReader();
                                reader.onload = function(file) { block['vars'][i]['value'] = btoa(file.target.result); fupdatescript(); };
                                reader.readAsBinaryString(x.files[0]);
                            }
                        } else {
                            block['vars'][i]['value'] = Q('scriptXvalue_' + i).value;
                        }
                    }
                }
            }
            fupdatescript();
        }

        // Starting with a child element, go up one parent at a time until we find an element with an ID.
        function fgetParentWithId(x) { while (!x.id) { x = x.parentElement; } return x; }

        // Displays the list of script blocks to the HTML page. Each block is displayed with it's name, attributes and an edit button.
        function fupdatescript() {
            var x = '';
            for (var i in script_BlockScript) {
                x += '<div id=xblock_' + i + ' style=cursor:pointer;min-height:24px;background-color:#' + ((script_BlockScriptSelectedId == i) ? 'aaa' : 'ccc') + ';width:auto;padding:5px;margin:2px draggable=true onclick=script_fonclick(event,this) ondragenter=script_fondragenter(event,this) ondragleave=script_fondragleave(event,this) ondragstart=script_fondragstart(event,this) ondragend=script_fondragend(event,this) ondrop=script_fondrop(event,this) title="' + script_BlockScript[i]['desc'] + '"';
                // ###BEGIN###{ContextMenus}
                var cmenus = [];
                cmenus.push("Modificare..." + '#script_foneditclick('+i+')');
                cmenus.push("Elimina" + '#script_foneditclickEx(2,'+i+')');
                x += ' cm=\'' + cmenus.join('|') + '\'';
                // ###END###{ContextMenus}
                x += '><input style=float:right type=button value=Edit... onclick=script_foneditclick(' + i + ')><div style=font-size:16px><b>' + script_BlockScript[i].name + '</b>';
                if (script_BlockScript[i]['vars']) {
                    var r = 0;
                    x += '<table class="scriptBlockVar us" cellpadding=0 cellspacing=0 style=width:100%;border-radius:5px;margin-top:8px>';
                    for (var j in script_BlockScript[i]['vars']) {
                        var v = script_BlockScript[i]['vars'][j]['value'];
                        if (script_BlockScript[i]['vars'][j]['type'] == 4 && script_BlockScript[i]['vars'][j]['value'].length > 0) v = '*****';
                        if (script_BlockScript[i]['vars'][j]['type'] == 3) v = script_BlockScript[i]['vars'][j]['values'][script_BlockScript[i]['vars'][j]['value']];
                        if (script_BlockScript[i]['vars'][j]['type'] == 6) {
                            if (script_BlockScript[i]['vars'][j]['value']) { v = "File binario," + script_BlockScript[i]['vars'][j]['value'].length + " byte"; } else { v = "Non impostato"; }
                        }
                        x += '<tr title="' + script_BlockScript[i]['vars'][j]['desc'] + '"><td width=200px style="' + (r > 0 ? 'border-top:1px solid #a810a8' : '') + '"><p>' + script_BlockScript[i]['vars'][j]['name'] + '<td style="' + (r > 0 ? 'border-top:1px solid #a810a8' : '') + '">' + v;
                        r++;
                    }
                    x += '<tr><td style=height:3px></table>';
                }
                x += '</div></div>';
            }
            if (x == '') { x = '<div style=\"padding:15px;color:gray\">' + "Inizia lo script trascinando i blocchi dal lato sinistro in questa casella di script." + '<div>'; }
            QH('scriptblocks', x + '<div style=height:80px></div>');
            for (var i in script_BlockScript) { QS('xblock_' + i).borderLeft = (script_CurrentHighlightBlock == i) ? '3px solid black' : ''; }
            script_blocksToScript();
        }

        // Convert the list of blocks into a script that can be compiled
        function script_blocksToScript() {
            var script = '';
            if (script_BuildingBlocks) {
                if (script_BuildingBlocks['_start']) { script += '##### Starting Block #####\r\n' + script_BuildingBlocks['_start']['code'] + '\r\n\r\n'; }
                for (var i in script_BlockScript) {
                    var code = script_BlockScript[i]['code'];
                    code = code.split('%%%~%%%').join(i);
                    for (var j in script_BlockScript[i]['vars']) { code = code.split('%%%' + j + '%%%').join(script_BlockScript[i]['vars'][j]['value']); }
                    script += '##### Block: ' + script_BlockScript[i]['name'] + ' #####\r\nHighlightBlock __t ' + i + '\r\n' + code + '\r\n\r\n';
                }
                if (script_BuildingBlocks['_end']) { script += '##### Ending Block #####\r\n' + script_BuildingBlocks['_end']['code'] + '\r\nHighlightBlock\r\n'; }
            }
            Q('scriptarea').value = script;
        }

        // Highlight a script block. This is useful to know what block the script is currently running
        var script_CurrentHighlightBlock;
        function script_HighlightBlock(runner, x) {
            if (runner == editscriptstate) { // Only highlight blocks if the scrpt editor is running the script. If running a script on the page, don't highlight blocks in the editor.
                script_CurrentHighlightBlock = x;
                for (var i in script_BlockScript) { QS('xblock_' + i).borderLeft = (script_CurrentHighlightBlock == i) ? '3px solid black' : ''; }
            }
        }

        // Called by the "New..." button to reset the script editor to the start
        function script_newScriptDlg() {
            if (xxdialogMode) return;
            setDialogMode(11, "Nuovo script", 3, script_newScriptDlgOk, '<br>' + "Ripristinare e cancellare l'editor di script?");
        }

        // Clear the script editor
        function script_newScriptDlgOk() {
            script_setBuildBlocks(script_StartingBuildingBlocks);
            script_BlockScript = [];
            script_BlockScriptSelectedId = null;
            delete editscriptstate;
            scriptViewButton(script_BuildingBlocks?1:0);
            QH('variables', '');
            Q('scriptarea').value = '';
            resetScriptButton();
        }

        // Compile and reset a script to the starting position
        function resetScriptButton() {
            // Compile the script
            breakScriptButton();
            Q('compiledarea').value = rstr2hex(script_compile(Q('scriptarea').value, function(m) { messagebox("Errore di compilazione dello script", m); }));
            delete editscriptstate;

            // Reset the script environment
            Q('console').value = '';
            QH('variables', '');
            QH('EditScriptStatus', "Fermato");
            if (script_BuilderView == 1) { fupdatescript(); }
            if (Q('compiledarea').value.length == 0) return;

            // Create a new script runtime object
            var startvars = { '_interactive':1 };
            // ###BEGIN###{Certificates}
            startvars['_certificates'] = 1;
            // ###END###{Certificates}
            // ###BEGIN###{!Mode-Firmware}
            startvars['_mode'] = 'Firmware';
            // ###END###{!Mode-Firmware}
            // ###BEGIN###{!Mode-MeshCentral2}
            startvars['_mode'] = 'MeshCentral2';
            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            startvars['_mode'] = 'NodeWebkit';
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Mode-LMS}
            startvars['_mode'] = 'LMS';
            // ###END###{Mode-LMS}
            // ###BEGIN###{Mode-WebSite}
            startvars['_mode'] = 'WebSite';
            // ###END###{Mode-WebSite}
            editscriptstate = script_setup(hex2rstr(Q('compiledarea').value), startvars);
            editscriptstate.wsstack = wsstack;
            editscriptstate.amtstack = amtstack;
            editscriptstate.onStep = editscript_updateScriptState;
            editscriptstate.onConsole = editscript_console;
            editscript_updateScriptState(editscriptstate);
        }

        // Start running the script
        function runScriptButton() {
            if (editscriptstate == null) resetScriptButton();
            if (editscriptstate == null) return;
            editscriptstate.start(100);
        }

        // Stop/Pause the script
        function breakScriptButton() {
            if (editscriptstate == null) return;
            editscriptstate.stop();
        }

        // Run one step of the script
        function stepScriptButton() {
            if (editscriptstate == null) resetScriptButton();
            if (editscriptstate == null) return;
            breakScriptButton();
            editscriptstate.step();
        }

        // Display a new line into the script console
        function editscript_console(msg) {
            Q('console').value += (msg + '\n');
        }

        // Update the script state information and displayed variables
        var script_states = ["Fermato", "In esecuzione", "In pausa"];
        function editscript_updateScriptState(runstate) {
            // Update variables
            var r = '';
            if (runstate && runstate != null) {
                var vs = [];
                for (var i in runstate.variables) { if (!i.startsWith('__')) vs.push(i); }
                vs.sort();
                //for (var i in vs) { r += vs[i] + ' = ' + script_toString(runstate.variables[vs[i]]) + "\n"; }
                for (var i in vs) {
                    if (typeof runstate.variables[vs[i]] == 'object') {
                        r += '<b>' + vs[i] + '</b> = ' + ObjectToStringEx(runstate.variables[vs[i]], 2) + '<br>';
                    } else {
                        r += '<b>' + vs[i] + '</b> = ' + EscapeHtml(script_toString(runstate.variables[vs[i]])) + '<br>';
                    }
                }
            }
            QH('variables', r);

            // Update state
            r = "Fermato, nessuno script";
            if (runstate && runstate != null) { r = script_states[runstate.state]; if (runstate.state > 0) r += ', ' + runstate.ip + ' : ' + script_decompile(runstate.script, runstate.ip); }
            if (r.length > 50) { r = r.substring(0, 50) + "..."; }
            QH('EditScriptStatus', r);
        }

        // Return a string from any input, if the input is an object, stringify it.
        function script_toString(x) { if (typeof x == 'object') return JSON.stringify(x); return x; }

        // ###BEGIN###{FileSaver}
        // Save a script to disk, start by showing a dialog box to prompt to the filename.
        function script_saveScript(e) {
            if (xxdialogMode || scriptstate) return;
            if (e && (e.shiftKey == true)) {
                // Save as script block
                setDialogMode(11, "Script Block", 1, null, '<br><textarea id=scriptSaveScriptJsonBlock style=width:100%;height:200px;resize:vertical />');
                QH('scriptSaveScriptJsonBlock', script_fConvertScriptToJsonBlock(Q('scriptarea').value));
            } else {
                // Save as .mescript file
                // ###BEGIN###{!Mode-NodeWebkit}
                setDialogMode(11, "Save Script", 3, script_saveScriptOk, '<br><input id=scriptsavename style=width:100% value=test.mescript >');
                // ###END###{!Mode-NodeWebkit}
                // ###BEGIN###{Mode-NodeWebkit}
                var chooser = document.createElement('input');
                chooser.setAttribute('type', "file")
                chooser.setAttribute('nwsaveas', "script.mescript");
                chooser.addEventListener('change', function() {
                    require('fs').writeFile(this.value, JSON.stringify({
                        'scriptText': Q('scriptarea').value,
                        'mescript': btoa(script_compile(Q('scriptarea').value)),
                        'blocks': script_StartingBuildingBlocks,
                        'scriptBlocks': script_BlockScript
                    }, null, '  ').replace(/\n/g, '\r\n'), function () { });
                }, false);
                chooser.click();
                // ###END###{Mode-NodeWebkit}
            }
        }

        // Once the filename is selected, save the file.
        function script_saveScriptOk() {
            if (xxdialogMode) return;
            var x = JSON.stringify({
                'scriptText': Q('scriptarea').value,
                'mescript': btoa(script_compile(Q('scriptarea').value)),
                'blocks': script_StartingBuildingBlocks,
                'scriptBlocks': script_BlockScript
            }, null, '  ');
            saveAs(data2blob(x), Q('scriptsavename').value);
        }
        // ###END###{FileSaver}

// ###END###{Scripting-Editor}

// ###BEGIN###{CertificateManager}

        //
        // Certificate Manager
        //

        /*
        function issueCertButtonOk() {
            var certopen = getInputElement('certopen');
            var files = xxDragDropCertFiles;
            if (certopen) files = certopen.files;
            if (files && files.length == 1) {
                // Issue a certificate using this file
                var reader = new FileReader();
                reader.onload = issueCertButtonOk2;
                reader.readAsBinaryString(files[0]);
            } else {
                // Issue a certificate using a dummy CA
                issueCertButtonOk3(null);
            }
        }
        */

        var certificateStore = [];
        var currentCertificate = null;

        function cert_updateCertificateList() {
            var x = '', certcount = 0;
            if (currentCertificate == null && certificateStore.length > 0) { currentCertificate = certificateStore[0]; }
            certificateStore.sort(function (a, b) { var aa = a.cert.subject.getField('CN').value; var bb = b.cert.subject.getField('CN').value; if (aa > bb) { return 1; } if (aa < bb) { return -1; } return 0; });
            for (var y in certificateStore) {
                try {
                    var certificate = certificateStore[y], name = certificate.cert.subject.getField('CN').value, extra = [];
                    if (certificate['tlsauth']) { extra.push('<span title="' + "Questo certificato verrà utilizzato per autenticare questa console su Intel AMT." + '">' + "Autenticazione TLS" + '</span>'); }
                    if (certificate['trusted'] == true) { extra.push('<span title="' + "Confidiamo nei certificati firmati da questo certificato." + '">' + "di fiducia" + '</span>'); }
                    if (certificate['privateKey']) { extra.push('<span title="' + "Abbiamo la chiave privata per questo certificato." + '">' + "Chiave privata" + '</span>'); }
                    x += '<div style=margin:4px;cursor:pointer>';
                    x += '<img src=images-commander/cert' + ((certificate['privateKey'])?'2':'1') + '.png style=vertical-align:text-top;float:left;background-color:white;height:28px height=32 width=32 />';
                    x += '<div id=LCR-' + certificate['h'] + ' class=g1 style=float:left;height:28px>&nbsp;</div><div id=RCR-' + certificate['h'] + ' class=g2 style=float:right;height:28px>&nbsp;</div><div style=height:28px ';
                    // ###BEGIN###{ContextMenus}
                    var cmenus = [];
                    cmenus.push("Visualizza..." + '#cert_view(' + certificate['h'] +'")');
                    if (certificate['privateKey']) { cmenus.push("Emetti nuovo certificato ..." + '#cert_issueNew(' + certificate['h'] + ')'); }
                    cmenus.push("Esporta come .cer ..." + '#cert_saveCertCer(' + certificate['h'] + ')');
                    if (certificate['privateKey']) { cmenus.push("Esporta come .p12 ..." + '#cert_saveCertP12(' + certificate['h'] + ')'); }
                    x += ' cm=\'' + cmenus.join('|') + '\'';
                    // ###END###{ContextMenus}
                    x += ' onclick=\'cert_select(event, ' + certificate['h'] + ')\' id=CR-' + certificate['h'] + ' ondblclick=cert_view(' + certificate['h'] + ')>';
                    //x += '<input id=SC-' + certificate['h'] + ' type=checkbox style=float:left;margin-top:8px onclick=cert_onCertificateChecked()' + (certificate.checked?' checked':'') + ' />';
                    x += '<div style=float:right><span style=font-size:14px>' + extra.join(', ') + '</span>&nbsp;<input type=button value="' + "Visualizza..." + '" onclick=cert_view(' + certificate['h'] + ')>&nbsp;</div><div style=padding-top:2px>&nbsp;';
                    // ###BEGIN###{Look-BrandedCommander}
                    //x += '<img src=images-BrandedCommander/ComputerIcon.png style=vertical-align:text-top />&nbsp;';
                    // ###END###{Look-BrandedCommander}
                    //x += '<img src=certificate.png style=vertical-align:text-top height=28 width=24 />';
                    x += '<b style=font-size:16px>' + EscapeHtml(name) + '</b></div></div></div>';
                    certcount++;
                } catch (e) { delete certificateStore[y]; }
            }
            QV('id_certStartScreen', certcount == 0);
            QH('id_certManagerMainArea', x);
            cert_select();
        }

        function cert_view(h) {
            if (xxdialogMode) return;
            var x = '', certificate = getCertificate(h), cert = certificate.cert, commonName = cert.subject.getField('CN').value;
            var fingerprint = '', fingerprint2 = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex().toUpperCase();
            for (i = 0; i < fingerprint2.length; i++) { if ((i != 0) && (i % 2 == 0)) { fingerprint += ':'; } fingerprint += fingerprint2.substring(i, i + 1); }
            x += '<img src=images-commander/cert' + ((certificate['privateKey']) ? '2' : '1') + '.png style=vertical-align:text-top;float:right;height:28px height=32 width=32 />';
            x += '<input id=certTrustedCheck type=checkbox>' + "Questo è un certificato attendibile" + '<br>';
            var extKeyUsage = null;
            for (var i in certificate.cert.extensions) { if (certificate.cert.extensions[i].id == '2.5.29.37') { extKeyUsage = certificate.cert.extensions[i]; } }
            if ((certificate['privateKey']) && (extKeyUsage != null) && (extKeyUsage['2.16.840.1.113741.1.2.1'] == true)) { x += '<div><input id=certMutualAuth type=checkbox>' + "Utilizzare per l'autenticazione della console TLS" + '<br></div>'; }
            x += '<br>';
            // ###BEGIN###{FileSaver}
            var y = atob(certificate['certbin']).length + " byte," + '<a style=cursor:pointer;color:blue onclick=cert_saveCertCer(' + h + ',1)>' + NoBreak("Salva .cer") + '</a>';
            if (certificate['privateKey']) { y += ', <a style=cursor:pointer;color:blue onclick=cert_saveCertP12(' + h + ')>' + NoBreak("Salva .p12") + '</a>'; }
            y += ', <a style=cursor:pointer;color:blue onclick=cert_saveCertCer(' + h + ',2)>' + NoBreak("Salva .pem") + '</a>';
            x += addHtmlValueNoTitle("Certificato", y);
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            //x += addHtmlValueNoTitle("Certificate", c.X509Certificate.length + " bytes");
            // ###END###{!FileSaver}
            // Decode certificate usages
            y = [];
            if (extKeyUsage != null) {
                if (extKeyUsage.clientAuth == true) { y.push(NoBreak("Client TLS")); }
                if (extKeyUsage.codeSigning == true) { y.push(NoBreak("Firma del codice")); }
                if (extKeyUsage.emailProtection == true) { y.push("E-mail"); }
                if (extKeyUsage.serverAuth == true) { y.push(NoBreak("Server TLS")); }
                if (extKeyUsage['2.16.840.1.113741.1.2.1'] == true) { y.push(NoBreak("Console Intel&reg; AMT")); }
                if (extKeyUsage['2.16.840.1.113741.1.2.2'] == true) { y.push(NoBreak("Agente Intel&reg; AMT")); }
                if (extKeyUsage['2.16.840.1.113741.1.2.3'] == true) { y.push(NoBreak("Attivazione Intel&reg; AMT")); }
                if (extKeyUsage.timeStamping == true) { y.push(NoBreak("Timestamp")); }
                if (y.length > 0) { x += addHtmlValueNoTitle("Utilizzo del certificato", y.join(', ') + '.') + '<br clear=all />'; }
            }
            x += '<br><div style=\"border-bottom:1px solid gray\"><i>' + "Oggetto del certificato" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.subject.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            x += addHtmlValueNoTitle("impronta digitale", fingerprint.substring(0,29) + '<br />' + fingerprint.substring(30));
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificato dell'Emittente" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.issuer.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            setDialogMode(11, "Certificato -" + EscapeHtml(commonName), 5, cert_viewex, x, certificate);
            Q('certTrustedCheck').checked = (certificate['trusted'] == true);
            if (certificate['privateKey'] && Q('certMutualAuth')) { Q('certMutualAuth').checked = (certificate['tlsauth'] == true); }
        }

        function cert_saveCertCer(h,type) {
            var certificate = getCertificate(h), cert = certificate.cert, commonName = cert.subject.getField('CN').value;
            // ###BEGIN###{!Mode-NodeWebkit}
            //saveAs(data2blob(xxCertificates[h].X509Certificate), xxCertificates[h].XSubject['CN'] + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            if (type == 1) { // .cer format
                chooser.setAttribute('nwsaveas', commonName + '.cer');
                chooser.addEventListener('change', function () { require('fs').writeFile(this.value, certificate['certbin'], 'base64', function () { }); }, false);
            } else if (type == 2) { // .pem format
                chooser.setAttribute('nwsaveas', commonName + '.pem');
                chooser.addEventListener('change', function () {
                    var ptr = 0, xcert = '';
                    // Write the public certificate
                    while (ptr < certificate['certbin'].length) { xcert += certificate['certbin'].substring(ptr, ptr + Math.min(certificate['certbin'].length - ptr, 64)) + '\r\n'; ptr += 64; }
                    xcert = '-----BEGIN CERTIFICATE-----\r\n' + xcert + '-----END CERTIFICATE-----\r\n';
                    if (certificate['privateKeyBin']) { xcert += '\r\n' + certificate['privateKeyBin']; } // Write the private key
                    require('fs').writeFile(this.value, xcert, function () { });
                }, false);
            }
            chooser.click();
            setDialogMode(0);
            // ###END###{Mode-NodeWebkit}
        }

        function cert_saveCertP12(h) {
            // Prompt to the PKCS12 password
            var x = "Immettere una password della chiave privata del certificato." + '<br/><br/><div style=height:26px><input id=idx_filepass1 type=password onkeyup=cert_saveCertP12Update() style=float:right;width:200px><div>' + "Parola d'ordine" + '</div></div><div style=height:26px><input id=idx_filepass2 type=password onkeyup=cert_saveCertP12Update() style=float:right;width:200px><div>' + "Parola d'ordine" + '</div></div>';
            setDialogMode(11, "Password del certificato", 3, cert_saveCertP12b, x, h);
            cert_saveCertP12Update();
        }

        function cert_saveCertP12Update() {
            QE('idx_dlgOkButton', (Q('idx_filepass1').value == Q('idx_filepass2').value) && (Q('idx_filepass1').value.length > 0));
        }

        function cert_saveCertP12b(b, h) {
            var certificate = getCertificate(h), cert = certificate.cert, commonName = cert.subject.getField('CN').value, pass = Q('idx_filepass1').value;
            // ###BEGIN###{!Mode-NodeWebkit}
            //saveAs(data2blob(xxCertificates[h].X509Certificate), xxCertificates[h].XSubject['CN'] + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', commonName + '.p12');
            chooser.addEventListener('change', function() {
                require('fs').writeFile(this.value, forge.util.encode64(forge.asn1.toDer(forge.pkcs12.toPkcs12Asn1(certificate['privateKey'], certificate['cert'], pass)).getBytes()), 'base64', function () { });
            }, false);
            chooser.click();
            setDialogMode(0);
            // ###END###{Mode-NodeWebkit}
        }

        function cert_viewex(b, certificate) {
            if (b == 2) {
                cert_removeCertificateEx(certificate['h']);
            } else {
                var update = 0;
                if (certificate['trusted'] != Q('certTrustedCheck').checked) { certificate['trusted'] = Q('certTrustedCheck').checked; update = 1; }
                if ((certificate['privateKey']) && Q('certMutualAuth') && (certificate['tlsauth'] != Q('certMutualAuth').checked)) {
                    for (var y in certificateStore) { certificateStore[y]['tlsauth'] = false; }
                    certificate['tlsauth'] = Q('certMutualAuth').checked;
                    update = 1;
                }
                if (update == 1) { cert_updateCertificateList(); cert_saveCertificates(); }
            }
        }

        function cert_removeCertificateEx(h) {
            cert_deleteCertificatesEx(2, [ getCertificate(h) ]);
        }

        function cert_select(e, h) {
            if (h) { currentCertificate = getCertificate(h); /*updateComputerDetails();*/ }
            for (var y in certificateStore) {
                var certificate = certificateStore[y];
                var sel = (currentCertificate != null && certificate['h'] == currentCertificate['h']);
                QS('CR-' + certificate['h'])['background-color'] = sel ? '#a0a0a0' : '#c9c9c9';
                Q('LCR-' + certificate['h']).classList.remove('g1');
                Q('LCR-' + certificate['h']).classList.remove('g1s');
                Q('RCR-' + certificate['h']).classList.remove('g2');
                Q('RCR-' + certificate['h']).classList.remove('g2s');
                Q('LCR-' + certificate['h']).classList.add(sel ? 'g1s' : 'g1');
                Q('RCR-' + certificate['h']).classList.add(sel ? 'g2s' : 'g2');
            }
            QE('IssueCertButton', (currentCertificate != null) && (currentCertificate['privateKey']));
        }

        function getCertificate(h) { for (var i in certificateStore) { if (certificateStore[i]['h'] == h) return certificateStore[i]; } return null; }
        function getCertificateWithKeyCount(h) { for (var i in certificateStore) { var c = 0; if (certificateStore[i]['privateKey']) { c++; } } return c; }
        function getTlsAuthCertificate() { for (var i in certificateStore) { if (certificateStore[i]['tlsauth'] == true) return certificateStore[i]; } return null; }

        function cert_onCertificateChecked() {
            for (var y in certificateStore) { certificateStore[y].checked = Q('SC-' + certificateStore[y]['h']).checked; }
        }

        function cert_deleteCertificates() {
            if (xxdialogMode) return;
            // Figure out how many certificates are selected.
            var clist = [];
            for (var y in certificateStore) { if (certificateStore[y].checked == true) { clist.push(certificateStore[y]); } }
            if (clist.length == 0) { clist.push(currentCertificate); }
            if (clist.length == 1) {
                setDialogMode(11, "Elimina certificati", 3, cert_deleteCertificatesEx, '<br>' + "Elimina 1 certificato?", clist);
            } else {
                setDialogMode(11, "Elimina certificati", 3, cert_deleteCertificatesEx, '<br>' + format("Eliminare {0} certificati?", clist.length), clist);
            }
        }

        function cert_deleteCertificatesEx(button, clist) {
            for (var i in clist) {
                var handleToDelete = clist[i]['h'];
                if ((currentCertificate != null) && (currentCertificate['h'] == handleToDelete)) { currentCertificate = null; }
                for (x = 0; x < certificateStore.length; x++) { if (certificateStore[x]['h'] == handleToDelete) { certificateStore.splice(x, 1); } }
            }
            cert_saveCertificates();
            cert_updateCertificateList();
            //updateComputerDetails();
        }

        function cert_loadCertificates() {
            // ###BEGIN###{Mode-NodeWebkit}
            var ctext = null;
            try { ctext = localStorage.getItem('certificates'); } catch (ex) { }
            if (ctext) {
                try { computerlist = JSON.parse(ctext); } catch (e) {
                    if (ctext.length > 512) { // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                        var crypto = require('crypto'), k = ctext.substring(0, 512), crypted = ctext.substring(512), decipher = crypto.createDecipher('aes-256-ctr', k), dec = decipher.update(crypted, 'hex', 'utf8');
                        dec += decipher.final('utf8');
                        var certificateStore2 = JSON.parse(dec);
                        if (Array.isArray(certificateStore2) == false) { certificateStore2 = []; }
                        for (var i in certificateStore2) {
                            try {
                                certificateStore2[i].checked = false;
                                if (certificateStore2[i]['certbin']) { certificateStore2[i]['cert'] = forge.pki.certificateFromAsn1(forge.asn1.fromDer(atob(certificateStore2[i]['certbin']))); }
                                if (certificateStore2[i]['privateKeyBin']) { certificateStore2[i]['privateKey'] = forge.pki.privateKeyFromPem(certificateStore2[i]['privateKeyBin']); }
                            } catch (e) { delete certificateStore2[i]; }
                        }
                        certificateStore = [];
                        for (var i in certificateStore2) { if (typeof certificateStore2[i] == 'object') certificateStore.push(certificateStore2[i]); }
                    }
                }
            }
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            //var ctext = null;
            //try { ctext = localStorage.getItem('computers'); } catch (ex) { }
            //if (ctext) { computerlist = JSON.parse(ctext); }
            // ###END###{!Mode-NodeWebkit}
            cert_updateCertificateList();
        }

        function cert_saveCertificates() {
            // ###BEGIN###{Mode-NodeWebkit}
            const crypto = require('crypto'); 
            crypto.randomBytes(256, function(err, buf) {
                if (err) throw err; // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                var k = buf.toString('hex'), cipher = crypto.createCipher('aes-256-ctr', k), crypted = cipher.update(JSON.stringify(certificateStore), 'utf8', 'hex');
                crypted += cipher.final('hex');
                try { localStorage.setItem('certificates', k + crypted); } catch (ex) { }
            });
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            //try { localStorage.setItem('computers', JSON.stringify(computerlist)); } catch (ex) { }
            // ###END###{!Mode-NodeWebkit}
        }

        function cert_createNew() {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certcn style=float:right;width:230px><div style=padding-top:4px>' + "Nome comune" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certo style=float:right;width:230px><div style=padding-top:4px>' + "Organizzazione" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certst style=float:right;width:230px><div style=padding-top:4px>' + "Stato / Provincia" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certc style=float:right;width:230px><div style=padding-top:4px>' + "Nazione" + '</div></div>';
            setDialogMode(11, "Crea certificato radice", 3, cert_createNewEx, x);
            cert_createNew_Update();
        }

        function cert_createNew_Update() {
            x = (getInputElement('certcn').value != '' && getInputElement('certo').value != '' && getInputElement('certst').value != '' && getInputElement('certc').value != '');
            QE('idx_dlgOkButton', x);
        }

        // --- Extended Key Usage OID's ---
        // 1.3.6.1.5.5.7.3.1            = TLS Server certificate
        // 1.3.6.1.5.5.7.3.2            = TLS Client certificate
        // 2.16.840.1.113741.1.2.1      = Intel AMT Remote Console
        // 2.16.840.1.113741.1.2.2      = Intel AMT Local Console
        // 2.16.840.1.113741.1.2.3      = Intel AMT Client Setup Certificate (Zero-Touch)

        function cert_createNewEx(b, rootCert) {
            // Generate a keypair and create an X.509v3 certificate
            var keys = forge.pki.rsa.generateKeyPair(2048);
            var cert = forge.pki.createCertificate();
            cert.publicKey = keys.publicKey;
            cert.serialNumber = '' + Math.floor((Math.random() * 100000) + 1);
            cert.validity.notBefore = new Date(2018, 0, 1);
            //cert.validity.notBefore.setFullYear(cert.validity.notBefore.getFullYear() - 1); // Create a certificate that is valid one year before, to make sure out-of-sync clocks don't reject this cert.
            cert.validity.notAfter = new Date(2049, 11, 31);
            //cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 20);
            var attrs = [
                { name: 'commonName', value: Q('certcn').value },
                { name: 'countryName', value: Q('certc').value },
                { shortName: 'ST', value: Q('certst').value },
                { name: 'organizationName', value: Q('certo').value }
            ];
            cert.setSubject(attrs);

            if (rootCert) {
                // Use root attributes
                cert.setIssuer(rootCert['cert'].subject.attributes);
            } else {
                // Use our own attributes
                cert.setIssuer(attrs);
            }

            if (rootCert == undefined) {
                // Create a root certificate
                cert.setExtensions([{
                    name: 'basicConstraints',
                    cA: true
                }, {
                    name: 'nsCertType',
                    sslCA: true,
                    emailCA: true,
                    objCA: true
                }, {
                    name: 'subjectKeyIdentifier'
                }]);
            } else {
                // Figure out the extended key usages
                var extKeyUsage = { name: 'extKeyUsage' }
                if (Q('d11_cu1').checked) { extKeyUsage['2.16.840.1.113741.1.2.1'] = true; extKeyUsage.clientAuth = true; }
                if (Q('d11_cu2').checked) { extKeyUsage['2.16.840.1.113741.1.2.2'] = true; extKeyUsage.clientAuth = true; }
                if (Q('d11_cu3').checked) { extKeyUsage['2.16.840.1.113741.1.2.3'] = true; extKeyUsage.clientAuth = true; }
                if (Q('d11_cu4').checked) { extKeyUsage.serverAuth = true; }
                if (Q('d11_cu5').checked) { extKeyUsage.clientAuth = true; }
                if (Q('d11_cu6').checked) { extKeyUsage.emailProtection = true; }
                if (Q('d11_cu7').checked) { extKeyUsage.codeSigning = true; }
                if (Q('d11_cu8').checked) { extKeyUsage.timeStamping = true; }

                // Create a leaf certificate
                cert.setExtensions([{
                    name: 'basicConstraints'
                }, {
                    name: 'keyUsage',
                    keyCertSign: true,
                    digitalSignature: true,
                    nonRepudiation: true,
                    keyEncipherment: true,
                    dataEncipherment: true
                }, extKeyUsage, {
                    name: 'nsCertType',
                    client: Q('d11_cu5').checked,
                    server: Q('d11_cu4').checked,
                    email: Q('d11_cu6').checked,
                    objsign: Q('d11_cu7').checked,
                }, {
                    name: 'subjectKeyIdentifier'
                } ]);
            }

            // Self-sign certificate
            if (rootCert) {
                cert.sign(rootCert['privateKey'], forge.md.sha256.create());
            } else {
                cert.sign(keys.privateKey, forge.md.sha256.create());
            }

            // Save the certificate in the store
            certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(hex2rstr(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex())), 'privateKey': keys.privateKey, 'privateKeyBin': forge.pki.privateKeyToPem(keys.privateKey), 'checked': false });
            cert_saveCertificates();
            cert_updateCertificateList();
        }

        function cert_issueNew() {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certcn style=float:right;width:230px><div style=padding-top:4px>' + "Nome comune" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certo style=float:right;width:230px><div style=padding-top:4px>' + "Organizzazione" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certst style=float:right;width:230px><div style=padding-top:4px>' + "Stato / Provincia" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certc style=float:right;width:230px><div style=padding-top:4px>' + "Nazione" + '</div></div>';
            x += '<div>Certificate Usages</div><ul style="list-style-type:none;height:100px;overflow:auto;width:100%;border: 1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0">';
            x += '<li><label><input type=checkbox id=d11_cu1>' + "Console Intel&reg; AMT" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu2>' + "Agente Intel&reg; AMT" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu3>' + "Attivazione Intel&reg; AMT" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu4>' + "Server TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu5>' + "Client TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu6>' + "Protezione e-mail" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu7>' + "Firma del codice" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu8>' + "Timestamp" + '</label></li>';
            x += '</ul>';
            setDialogMode(11, format("Rilascio certificato firmato da {0}", currentCertificate.cert.subject.getField('CN').value), 3, cert_createNewEx, x, currentCertificate);
            cert_issueNew_Update();
        }

        function cert_issueNew_Update() {
            x = (getInputElement('certcn').value != '' && getInputElement('certo').value != '' && getInputElement('certst').value != '' && getInputElement('certc').value != '');
            QE('idx_dlgOkButton', x);
        }

        function cert_importCert() {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = Q('certOpenFile');
            if (chooser.getAttribute('eventset') != 1) {
                chooser.setAttribute('eventset', '1');
                chooser.addEventListener('change', cert_importCertOk, false);
            }
            chooser.value = null;
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function cert_importCertOk2(e) {
            haltEvent(e);
            if (e.dataTransfer.files.length == 1) {
                var reader = new FileReader();
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.p12') || e.dataTransfer.files[0].name.toLowerCase().endsWith('.pfx')) {
                    reader.onload = cert_importCertOkP12;
                } else {
                    reader.onload = cert_importCertOkCER;
                }
                reader.readAsBinaryString(e.dataTransfer.files[0]);
            }
        }

        function cert_importCertOk() {
            var x = Q('certOpenFile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            if (x.files[0].name.toLowerCase().endsWith('.p12') || x.files[0].name.toLowerCase().endsWith('.pfx')) { reader.onload = cert_importCertOkP12; } else { reader.onload = cert_importCertOkCER; }
            reader.readAsBinaryString(x.files[0]);
        }

        function cert_importCertOkP12(file) {
            // Prompt to the PKCS12 password
            var x = "Il file del certificato selezionato richiede una password." + '<br/><br/><div style=height:26px><input id=idx_filepass type=password style=float:right;width:200px><div>' + "Parola d'ordine" + '</div></div>';
            setDialogMode(11, "Password del certificato", 3, cert_importCertOkP12b, x, file);
        }

        function cert_importCertOkP12b(button, file) {
            // Try to decode the PKCS12 file
            var p12;
            try { p12 = forge.pkcs12.pkcs12FromAsn1(forge.asn1.fromDer(file.target.result), Q('idx_filepass').value); } catch (e) { setDialogMode(11, "File di certificato", 1, function() {}, "Password del certificato non valida o impossibile decodificare il file."); return; }
            var bags1 = p12.getBags({bagType: forge.pki.oids.certBag});
            var cert = bags1[forge.pki.oids.certBag][0].cert;
            var bags2 = p12.getBags({bagType: '1.2.840.113549.1.12.10.1.2'})
            var key = bags2['1.2.840.113549.1.12.10.1.2'][0].key;
            certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(hex2rstr(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex())), 'privateKey': key, 'privateKeyBin': forge.pki.privateKeyToPem(key), 'checked': false });
            cert_saveCertificates();
            cert_updateCertificateList();
        }

        function cert_importCertOkCER(file) {
            var cert, str = file.target.result;
            var pemcert = cert_getMiddleString(str, '-----BEGIN CERTIFICATE-----', '-----END CERTIFICATE-----');
            var pemkey = cert_getMiddleString(str, '-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----');
            if (pemkey == null) { pemkey = cert_getMiddleString(str, '-----BEGIN RSA PRIVATE KEY-----', '-----END RSA PRIVATE KEY-----'); }
            if (pemcert != null) {
                // Try to decode the .PEM file
                try { cert = forge.pki.certificateFromPem(pemcert); } catch (e) { setDialogMode(11, "File di certificato", 1, function () { }, "Impossibile decodificare il file PEM."); return; }
                if (pemkey == null) {
                    // Public key only
                    certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()), 'checked': false });
                } else {
                    // Public and private key
                    var privatekey;
                    try { privatekey = forge.pki.privateKeyFromPem(pemkey); } catch (e) { setDialogMode(11, "File di certificato", 1, function () { }, "Impossibile decodificare la chiave privata PEM."); return; }
                    certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()), 'privateKey': privatekey, 'privateKeyBin': forge.pki.privateKeyToPem(privatekey), 'checked': false });
                }
            } else {
                // Try to decode the .CER file, public key only
                try { cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(str)); } catch (e) { setDialogMode(11, "File di certificato", 1, function () { }, "Impossibile decodificare il file del certificato."); return; }
                certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(file.target.result), 'checked': false });
            }
            cert_saveCertificates();
            cert_updateCertificateList();
        }

        function cert_getMiddleString(str, start, end) { var a = str.indexOf(start), b = str.indexOf(end); if ((a == -1) || (b == -1) || (b < a)) return null; return str.substring(a, b + end.length); }

// ###END###{CertificateManager}
        
// ###BEGIN###{USBSetup}

        //
        // USB SETUP.BIN
        //

        function usb_newSetupBin() {
            if (xxdialogMode) return;
            idx_d14version.value = 4;
            idx_d14consume.value = 1;
            setDialogMode(14, "Crea un nuovo file Setup.bin", 3, usb_newSetupBinOk);
        }

        function usb_newSetupBinOk(r) {
            if (r == 1) { setupbin = AmtSetupBinCreate(idx_d14version.value, idx_d14consume.value); } // OK Button
            usb_displaySetupBin();
        }

        function usb_openSetupBin() {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('accept', '.bin')
            chooser.addEventListener('change', function() {
                setupbin = AmtSetupBinDecode(require('fs').readFileSync(this.value, 'binary'));
                if (!setupbin) { messagebox("Apri il file", "File setup.bin non valido o danneggiato. Incapace di aprire."); } else { usb_displaySetupBin(); }
            }, false);
            chooser.value = null;
            chooser.click();
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            setDialogMode(15, "Open Setup.bin file", 3, usb_openSetupBinOk);
            // ###END###{!Mode-NodeWebkit}
        }

        function usb_openSetupBinOk() {
            var x = Q('d15setupbinfile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = usb_onSetupBinRead;
            reader.readAsBinaryString(x.files[0]);
        }

        // ###BEGIN###{FileSaver}
        function usb_saveSetupBin() {
            if (xxdialogMode || !setupbin) return;
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(AmtSetupBinEncode(setupbin)), 'setup.bin');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', 'setup.bin');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, AmtSetupBinEncode(setupbin), 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        function usb_onSetupBinRead(file) {
            setupbin = AmtSetupBinDecode(file.target.result);
            if (!setupbin) { messagebox("Apri il file", "File setup.bin non valido o danneggiato. Incapace di aprire."); } else { usb_displaySetupBin(); }
        }

        function usb_displaySetupBin() {
            QV('id_StartupScreen', !setupbin);
            // ###BEGIN###{FileSaver}
            QV('id_saveSetupBin', setupbin);
            // ###END###{FileSaver}
            if (!setupbin) { return QH('id_SetupBinArea', ''); }
            
            // Update record count
            var consumed = 0;
            for (var i in setupbin.records) { if ((setupbin.records[i].flags & 1) == 0) { consumed++; } }
            setupbin.dataRecordsConsumed = consumed;

            // Main Header            
            var x = '<table onclick=usb_editheader(event) class="log1 us" cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px;cursor:pointer><tr><td><p><td>';
            x += '<tr><td class=r2 style=padding-left:15px>';
            x += '<div style=float:right;margin-right:12px onclick=usb_addRecordSetupBin()><a><u title=\'' + "Aggiungi un nuovo record" + '\'>' + "Aggiungi record" + '</u></a></div>';
            x += '<div><strong>' + format("Versione del file Intel&reg; AMT Setup.bin {0}. {1}", setupbin.majorVersion, + setupbin.minorVersion) + '</strong>.</div>';
            x += (((setupbin.flags & 1) == 0) ? 'Records will be consumed.' : 'Records will not be consumed.');
            x += '<br>' + format("Record: {0}, consumati: {1}", setupbin.records.length, setupbin.dataRecordsConsumed)+ '<br>';
            x += '<tr style=height:4px></table>';

            // Display each record
            for (var i in setupbin.records) {
                var rec = setupbin.records[i];
                x += '<div style=height:4px></div><table class="log1 us" cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td><tr><td class=r2 style=padding-left:15px;cursor:pointer>';
                x += '<div style=float:right;margin-right:12px onclick="usb_addvariable(event,' + i + ')"><a><u title="' + "Aggiungi una nuova variabile" + '">' + "Aggiungi variabile" + '</u></a></div>';
                x += '<div onclick=\'usb_editrecord(event, ' + i + ')\'>' + "Disco #" + '<strong>' + (+i + 1) + '</strong>. ' + "Questo record è: " + '<strong>' + ((rec.flags & 1) ? "Valido" : "consumato") + ((rec.flags & 2) ? ", Strapazzate" : '') + '</strong></div>';

                // Display each variable
                for (var j in rec.variables) {
                    var v = rec.variables[j], val = v.value;
                    if (AmtSetupBinVarIds[v.moduleid][v.varid][2] && AmtSetupBinVarIds[v.moduleid][v.varid][2][val]) { val = AmtSetupBinVarIds[v.moduleid][v.varid][2][val]; }
                    if (v.moduleid == 2 && v.varid == 8) {
                        var hashtype = val.charCodeAt(0);
                        if (hashtype >= 0 && hashtype <= 3) {
                            var hashsize = [20, 32, 48][hashtype - 1];
                            var hash = rstr2hex(val.substring(1, hashsize + 1));
                            var hashnamesize = val.charCodeAt(1 + hashsize);
                            var hashname = val.substring(2 + hashsize, 2 + hashsize + hashnamesize)
                            val = ['SHA1', 'SHA256', 'SHA384'][hashtype - 1] + ', ' + hashname + ', ' + hash;
                        }
                    }
                    if (v.moduleid == 2 && v.varid == 17) {
                        val = val.charCodeAt(3) + '.' + val.charCodeAt(2) + '.' + val.charCodeAt(1) + '.' + val.charCodeAt(0);
                    }
                    x += '<div style=margin-right:12px><table onclick=\'usb_editvariable(event,' + i + ',' + j + ')\' class=\'itemBar us\' cellpadding=0 cellspacing=0 style=width:100%;border-radius:4px;margin-top:2px;margin-bottom:2px;padding:0><tr><td><p style=float:right;margin-right:8px><b>' + val + '</b><p>' + v['desc'] + '<tr style=height:4px></table></div>';
                }

                x += '<tr style=height:4px></table>';
            }

            QH('id_SetupBinArea', x);
        }

        function usb_addRecordSetupBin() {
            if (xxdialogMode) return;
            d13valid.checked = 1;
            d13scramble.checked = 0;
            QV('d13ScrambledRecordSpan', setupbin.majorVersion > 3);
            setDialogMode(13, "Nuovo record #", 3, usb_addRecordSetupBinOk);
        }

        function usb_addRecordSetupBinOk() {
            var r = {};
            r.typeIdentifier = 1;
            r.flags = (d13valid.checked ? 1 : 0) + (d13scramble.checked ? 2 : 0);
            r.chunkCount = 0;
            r.headerByteCount = 0;
            r.number = 0;
            r.variables = [];
            setupbin.records.push(r);
            usb_displaySetupBin();
        }

        function usb_editheader(e) {
            if (xxdialogMode) return;
            haltEvent(e);
            idx_d14version.value = setupbin.majorVersion;
            idx_d14consume.value = (setupbin.flags & 1);
            setDialogMode(14, "Modifica intestazione", 7, usb_editheaderok);
        }

        function usb_editheaderok(r) {
            if (r == 2) {
                delete setupbin;
            } else {
                setupbin.majorVersion = idx_d14version.value;
                setupbin.flags = idx_d14consume.value;
            }
            usb_displaySetupBin();
        }

        function usb_editrecord(e, i) {
            if (xxdialogMode) return;
            selectedRecord = i;
            selectedVariable = -1;
            haltEvent(e);
            d13valid.checked = (setupbin.records[selectedRecord].flags & 1);
            d13scramble.checked = (setupbin.records[selectedRecord].flags & 2);
            QV('d13ScrambledRecordSpan', setupbin.majorVersion > 3);
            setDialogMode(13, format("Modifica record # {0}", (i + 1)), 7, usb_editrecordok);
        }

        function usb_editrecordok(r) {
            if (r == 1) { setupbin.records[selectedRecord].flags = (d13valid.checked ? 1 : 0) + (d13scramble.checked ? 2 : 0); } // Edit Record
            if (r == 2) { setupbin.records.splice(selectedRecord, 1); } // Delete Record
            usb_displaySetupBin();
        }

        function usb_editvariable(e, i, j) {
            if (xxdialogMode) return;
            selectedRecord = i;
            selectedVariable = j;
            var modid = setupbin.records[i].variables[j].moduleid;
            var varid = setupbin.records[i].variables[j].varid;
            d16type.value = modid + '-' + varid;
            d16type.disabled = true;
            usb_ond16typechange();
            QV('d16genericvalue', false);
            QV('d16customvalue', false);
            if (modid == 2 && varid == 8) {
                var x = '<div style=height:26px><select id=idx_d16valc1 style=float:right;width:260px onchange=usb_ond16checkhash()><option value=1>' + "SHA1" + '</option>';
                if (setupbin.majorVersion >= 3) { x += '<option value=2>SHA256</option><option value=3>' + "SHA384" + '</option>'; }
                x += '</select><div>' + "Tipo di hash" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc2 style=float:right;width:260px onkeyup=usb_ond16checkhash()><div>' + "Hash (HEX)" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc3 style=float:right;width:260px onkeyup=usb_ond16checkhash() maxlength=31><div>' + "Nome hash" + '</div></div>';
                QH('d16customvalue', x);
                QV('d16customvalue', true);
                var val = setupbin.records[i].variables[j].value;
                var hashtype = val.charCodeAt(0);
                if (hashtype >= 0 && hashtype <= 3) {
                    var hashsize = [20, 32, 48][hashtype - 1];
                    var hash = rstr2hex(val.substring(1, hashsize + 1));
                    var hashnamesize = val.charCodeAt(1 + hashsize);
                    var hashname = val.substring(2 + hashsize, 2 + hashsize + hashnamesize)
                    val = ["SHA1", "SHA256", "SHA384"][hashtype - 1] + ', ' + hashname + ', ' + hash;
                    Q('idx_d16valc1').value = hashtype;
                    Q('idx_d16valc2').value = hash;
                    Q('idx_d16valc3').value = hashname;
                }
                usb_ond16checkhash();
            } else if (modid == 2 && varid == 17) {  // Provisioning server address
                QV('d16genericvalue', true);
                var ip = setupbin.records[i].variables[j].value;
                idx_d16value1.value = idx_d16value2.value = ip.charCodeAt(3) + '.' + ip.charCodeAt(2) + '.' + ip.charCodeAt(1) + '.' + ip.charCodeAt(0);
            } else {
                QV('d16genericvalue', true);
                idx_d16value1.value = idx_d16value2.value = setupbin.records[i].variables[j].value;
            }
            haltEvent(e);
            setDialogMode(16, format("Modifica record # {0}, variabile # {1}", (i + 1), (j + 1)), 7, usb_editvariableok);
        }

        function usb_editvariableok(r) {
            if (r == 1) { // OK
                var ids = d16type.value.split('-');
                var modid = +ids[0];
                var varid = +ids[1];
                var value = '';
                var vardescription = AmtSetupBinVarIds[modid][varid];
                if ((modid == 2) && (varid == 8)) {
                    value = String.fromCharCode(Q('idx_d16valc1').value) + hex2rstr(Q('idx_d16valc2').value) + String.fromCharCode(Q('idx_d16valc3').value.length) + Q('idx_d16valc3').value;
                } else {
                    if (vardescription[2]) { value = idx_d16value1.value; } else { value = idx_d16value2.value; }
                }
                if ((modid == 2) && (varid == 17)) {  // Provisioning server address
                    var ipSplit = value.split('.');
                    if (ipSplit.length != 4) return;
                    value = String.fromCharCode(parseInt(ipSplit[3]), parseInt(ipSplit[2]), parseInt(ipSplit[1]), parseInt(ipSplit[0]));
                }
                setupbin.records[selectedRecord].variables[selectedVariable].value = value;
            }
            if (r == 2) { setupbin.records[selectedRecord].variables.splice(selectedVariable, 1); } // Delete
            usb_displaySetupBin();
        }

        function usb_addvariable(e, i) {
            if (xxdialogMode) return;
            selectedRecord = i;
            d16type.value = '1-1';
            d16type.disabled = false;
            idx_d16value1.value = idx_d16value2.value = '';
            usb_ond16typechange();
            haltEvent(e);
            setDialogMode(16, format("Aggiungi variabile al record # {0}", (i + 1)), 3, usb_addvariableok);
        }

        function usb_addvariableok() {
            var ids = d16type.value.split('-');
            var modid = +ids[0];
            var varid = +ids[1];
            var value = '';
            var vardescription = AmtSetupBinVarIds[modid][varid];
            if ((modid == 2) && (varid == 8)) {
                value = String.fromCharCode(Q('idx_d16valc1').value) + hex2rstr(Q('idx_d16valc2').value) + String.fromCharCode(Q('idx_d16valc3').value.length) + Q('idx_d16valc3').value;
            } else {
                if (vardescription[2]) { value = idx_d16value1.value; } else { value = idx_d16value2.value; }
            }
            if ((modid == 2) && (varid == 17)) { // Provisioning server address
                var ipSplit = value.split('.');
                if (ipSplit.length != 4) return;
                value = String.fromCharCode(parseInt(ipSplit[3]), parseInt(ipSplit[2]), parseInt(ipSplit[1]), parseInt(ipSplit[0]));
            }

            // Create a new variable
            var v = {};
            v.moduleid = modid;
            v.varid = varid;
            v.length = -1;
            v.type = AmtSetupBinVarIds[modid][varid][0];
            v.desc = AmtSetupBinVarIds[modid][varid][1];
            v.value = value;
            setupbin.records[selectedRecord].variables.push(v);

            setupbin.records[selectedRecord].variables.sort(AmtSetupBinVariableCompare); // Sort the variables
            usb_displaySetupBin();
        }

        function usb_ond16typechange() {
            var ids = d16type.value.split('-');
            var modid = +ids[0];
            var varid = +ids[1];
            var vardescription = AmtSetupBinVarIds[modid][varid];
            QV('d16genericvalue', false);
            QV('d16customvalue', false);
            if (modid == 2 && varid == 8) {
                var x = '<div style=height:26px><select id=idx_d16valc1 style=float:right;width:260px onchange=usb_ond16checkhash()><option value=1>' + "SHA1" + '</option>';
                if (setupbin.majorVersion >= 3) { x += ('<option value=2>' + "SHA256" + '</option><option value=3>' + "SHA384" + '</option>'); }
                x += '</select><div>' + "Tipo di hash" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc2 style=float:right;width:260px onkeyup=usb_ond16checkhash()><div>' + "Hash (HEX)" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc3 style=float:right;width:260px onkeyup=usb_ond16checkhash() maxlength=31><div>' + "Nome hash" + '</div></div>';
                QV('d16customvalue', true);
                QH('d16customvalue', x);
                usb_ond16checkhash();
            } else {
                QV('d16genericvalue', true);
                if (vardescription[2]) {
                    QV('idx_d16value1', true);
                    QV('idx_d16value2', false);
                    var options = '';
                    for (var i in vardescription[2]) { options += '<option value="' + i + '">' + vardescription[2][i] }
                    QH('idx_d16value1', options);
                } else {
                    QV('idx_d16value1', false);
                    QV('idx_d16value2', true);
                }
            }
        }

        function usb_ond16checkhash() {
            var hashtype = Q('idx_d16valc1').value;
            var hashlen = hex2rstr(Q('idx_d16valc2').value).length;
            QE('idx_dlgOkButton', (Q('idx_d16valc3').value.length > 0) && ((hashtype == 1) && (hashlen == 20)) || ((hashtype == 2) && (hashlen == 32)) || ((hashtype == 3) && (hashlen == 48)));
        }

        var usb_alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

        function usb_computeChecksum(s) {
            var A = 0;
            for (var i = 0; i < s.length; i++) A += s.charCodeAt(i);
            return usb_alphabet[A % 36];
        }

        function usb_generateRandomPid() {
            var pid = '';
            for (var i = 0; i < 7; i++) { pid += usb_alphabet[random(36)]; }
            return pid + usb_computeChecksum(pid);
        }

        function usb_generateRandomPps()
        {
            var pps = '', s;
            for (var j = 0; j < 8; j++) {
                s = '';
                for (var i = 0; i < 3; i++) s += usb_alphabet[random(36)];
                pps += s + usb_computeChecksum(s);
            }
            return pps;
        }

        // ###END###{USBSetup}

        // ###BEGIN###{SessionRecording}

        var recFile = null;
        var recFilePtr = 0;
        var recFileStartTime = 0;
        var recFileLastTime = 0;
        var recFileEndTime = 0;
        var recFileMetadata = null;
        var recFileProtocol = 0;
        var agentDesktop = null;
        var agentTerminal = null;
        var amtDesktop = null;
        var srec_playing = 0; // 0 = Stopped, 1 = Pausing, 2 = Playing
        var readState = 0;
        var waitTimer = null;
        var waitTimerArgs = null;
        var srec_deskAspectRatio = 0;
        var currentDeltaTimeTotalSec = 0;

        function readNextBlock(func) {
            if ((recFilePtr + 16) > recFile.size) { QS('srec_progressbar').width = '100%'; func(-1); } else {
                var fr = new FileReader();
                fr.onload = function () {
                    var type = ReadShort(this.result, 0);
                    var flags = ReadShort(this.result, 2);
                    var size = ReadInt(this.result, 4);
                    var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
                    if ((recFilePtr + 16 + size) > recFile.size) { QS('srec_progressbar').width = '100%'; func(-1); } else {
                        var fr2 = new FileReader();
                        fr2.onload = function () {
                            recFilePtr += (16 + size);
                            if (recFileEndTime == 0) {
                                // File pointer progress bar
                                QS('srec_progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%';
                            } else {
                                // Time progress bar
                                QS('srec_progressbar').width = Math.floor(((recFileLastTime - recFileStartTime) / (recFileEndTime - recFileStartTime)) * 100) + '%';
                            }
                            func(type, flags, time, this.result);
                        };
                        fr2.readAsBinaryString(recFile.slice(recFilePtr + 16, recFilePtr + 16 + size));
                    }
                };
                fr.readAsBinaryString(recFile.slice(recFilePtr, recFilePtr + 16));
            }
        }

        function readLastBlock(func) {
            if (recFile.size < 32) { func(-1); } else {
                var fr = new FileReader();
                fr.onload = function () {
                    var type = ReadShort(this.result, 0);
                    var flags = ReadShort(this.result, 2);
                    var size = ReadInt(this.result, 4);
                    var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
                    if ((type == 3) && (size == 16) && (this.result.substring(16, 32) == 'MeshCentralMCREC')) { func(type, flags, time); } else { func(-1); }
                };
                fr.readAsBinaryString(recFile.slice(recFile.size - 32, recFile.size));
            }
        }

        function addInfo(name, value) { if (value == null) return ''; return addInfoNoEsc(name, EscapeHtml(value)); }

        function addInfoNoEsc(name, value) {
            if (value == null) return '';
            return '<span style=color:gray>' + EscapeHtml(name) + '</span>:&nbsp;<span style=font-size:20px;color:black>' + value + '</span><br/>';
        }

        function processFirstBlock(type, flags, time, data) {
            recFileProtocol = 0;
            if ((type != 1) || (flags != 0)) { cleanup(); return; }
            try { recFileMetadata = JSON.parse(data) } catch (ex) { cleanup(); return; }
            if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; }
            var x = '';
            x += addInfo("Tempo", recFileMetadata.time);
            if (recFileEndTime != 0) {
                var secs = Math.floor((recFileEndTime - time) / 1000);
                if (secs > 1) { x += addInfo("Durata", format("{0} secondi", secs)); } else { x += addInfo("Durata", "1 secondo"); }
            }
            x += addInfo("Nome utente", recFileMetadata.username);
            x += addInfo("ID utente", recFileMetadata.userid);
            x += addInfo("SessionID", recFileMetadata.sessionid);
            if (recFileMetadata.ipaddr1 && recFileMetadata.ipaddr2) { x += addInfo("indirizzi", format("Da {0} a {1}", recFileMetadata.ipaddr1, recFileMetadata.ipaddr2)); }
            x += addInfo("NodeID", recFileMetadata.nodeid);
            if (recFileMetadata.protocol) {
                var p = recFileMetadata.protocol;
                if (p == 1) { p = "Terminale MeshCentral"; }
                else if (p == 2) { p = "MeshCentral Desktop"; }
                else if (p == 100) { p = "Intel&reg; AMT WSMAN"; }
                else if (p == 101) { p = "Reindirizzamento Intel&reg; AMT"; }
                else if (p == 200) { p = "Intel&reg; AMT KVM"; }
                x += addInfoNoEsc("Protocollo", p);
            }
            QV('srec_DeskParent', false);
            QV('srec_TermParent', false);
            if (recFileMetadata.protocol == 1) {
                // MeshCentral remote terminal
                recFileProtocol = 1;
                x += '<br /><br /><span style=color:gray>' + "Premere [spazio] per riprodurre / mettere in pausa." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', false);
                recFileStartTime = recFileLastTime = time;
            }
            else if (recFileMetadata.protocol == 2) {
                // MeshCentral remote desktop
                recFileProtocol = 2;
                x += '<br /><br /><span style=color:gray>' + "Premere [spazio] per riprodurre / mettere in pausa." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', true);
                recFileStartTime = recFileLastTime = time;
                agentDesktop = CreateAgentRemoteDesktop('srec_Desk');
                agentDesktop.onScreenSizeChange = srec_deskAdjust;
                agentDesktop.State = 3;
                srec_deskAdjust();
            }
            else if (recFileMetadata.protocol == 101) {
                // Intel AMT Redirection
                recFileProtocol = 101;
                x += '<br /><br /><span style=color:gray>' + "Premere [spazio] per riprodurre / mettere in pausa." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', true);
                recFileStartTime = recFileLastTime = time;
                amtDesktop = CreateAmtRemoteDesktop('srec_Desk');
                amtDesktop.onScreenSizeChange = srec_deskAdjust;
                amtDesktop.State = 3;
                amtDesktop.Start();
                srec_deskAdjust();
            } else if (recFileMetadata.protocol == 200) {
                // Intel AMT Midstream KVM
                recFileProtocol = 200;
                x += '<br /><br /><span style=color:gray>' + "Premere [spazio] per riprodurre / mettere in pausa." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', true);
                recFileStartTime = recFileLastTime = time;
                amtDesktop = CreateAmtRemoteDesktop('srec_Desk');
                amtDesktop.onScreenSizeChange = srec_deskAdjust;
                amtDesktop.State = 3;
                amtDesktop.Start();
                if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; }
                if (recFileMetadata.graymode) { amtDesktop.graymode = recFileMetadata.graymode; }
                if (recFileMetadata.lowcolor) { amtDesktop.lowcolor = recFileMetadata.lowcolor; }
                amtDesktop.state = 3;
                srec_deskAdjust();
            }
            QV('srec_metadatadiv', true);
            QH('srec_metadatadiv', x);
            QH('srec_deskstatus', recFile.name);
        }

        function processBlock(type, flags, time, data) {
            if (type < 0) { srec_pause(); return; }
            var waitTime = Math.round((time - recFileLastTime) * parseFloat(Q('srec_PlaySpeed').value));
            if (waitTime < 5) {
                processBlockEx(type, flags, time, data);
            } else {
                waitTimerArgs = [type, flags, time, data]
                waitTimer = setTimeout(function () { waitTimer = null; processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]); }, waitTime);
            }
        }

        function processBlockEx(type, flags, time, data) {
            if (srec_playing == 0) return;
            var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0;

            // Update the clock
            var deltaTimeTotalSec = Math.floor((time - recFileStartTime) / 1000);
            if (currentDeltaTimeTotalSec != deltaTimeTotalSec) {
                currentDeltaTimeTotalSec = deltaTimeTotalSec;
                var deltaTimeHours = Math.floor(deltaTimeTotalSec / 3600);
                deltaTimeTotalSec -= (deltaTimeHours * 3600)
                var deltaTimeMinutes = Math.floor(deltaTimeTotalSec / 60);
                deltaTimeTotalSec -= (deltaTimeHours * 60)
                var deltaTimeSeconds = Math.floor(deltaTimeTotalSec);
                QH('srec_timespan', pad2(deltaTimeHours) + ':' + pad2(deltaTimeMinutes) + ':' + pad2(deltaTimeSeconds))
            }

            if ((type == 2) && flagBinary && !flagUser) {
                // Device --> User data
                if (recFileProtocol == 1) {
                    // MeshCentral Terminal
                    agentTerminal.ProcessData(data);
                } else if (recFileProtocol == 2) {
                    // MeshCentral Remote Desktop
                    agentDesktop.ProcessData(data);
                } else if (recFileProtocol == 101) {
                    // Intel AMT KVM
                    if ((readState == 0) && (rstr2hex(data).startsWith('4100000000000000'))) {
                        // We are not authenticated, KVM data starts here.
                        readState = 1;
                        if (data.length > 8) {
                            var view = new Uint8Array(data.length - 8);
                            for (var i = 8; i < data.length; i++) { view[i] = data.charCodeAt(i); }
                            amtDesktop.ProcessBinaryData(view.buffer);
                        }
                    } else if (readState == 1) {
                        var view = new Uint8Array(data.length);
                        for (var i = 0; i < data.length; i++) { view[i] = data.charCodeAt(i); }
                        amtDesktop.ProcessBinaryData(view.buffer);
                    }
                } else if (recFileProtocol == 200) {
                    // Intel AMT midstream KVM
                    var view = new Uint8Array(data.length);
                    for (var i = 0; i < data.length; i++) { view[i] = data.charCodeAt(i); }
                    amtDesktop.ProcessBinaryData(view.buffer);
                }
            } else if ((type == 2) && flagBinary && flagUser) {
                // User --> Device data
                if (recFileProtocol == 101) {
                    // Intel AMT KVM
                    if (rstr2hex(data) == '0000000008080001000700070003050200000000') { console.log('RGB8'); amtDesktop.bpp = 1; } // Switch to 1 byte per pixel, 256 colors
                    if (rstr2hex(data) == '000000000808000100FF00000000000000000000') { console.log('GRAY8'); amtDesktop.bpp = 1; obj.graymode = true; } // Switch to 1 byte per pixel, 256 grays
                    if (rstr2hex(data) == '0000000008040001000F00000000000000000000') { console.log('GRAY4'); amtDesktop.bpp = 1; obj.graymode = true; obj.lowcolor = true; } // Switch to 1 byte per pixel, 16 grays
                }
            }

            // This is a PNG screenshot of the display, load it and render it.
            if ((type == 3) && (recFileProtocol == 200)) {
                var tile = new Image();
                tile.src = 'data:image/png;base64,' + btoa(data);
                tile.onload = function () { amtDesktop.canvas.drawImage(tile, 0, 0); }
                tile.error = function () { }
            }

            recFileLastTime = time;
            if (srec_playing == 2) { readNextBlock(processBlock); }
        }

        function srec_cleanup() {
            recFile = null;
            recFilePtr = 0;
            recFileMetadata = null;
            srec_playing = 0;
            if (agentDesktop != null) { agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); agentDesktop = null; }
            if (amtDesktop != null) { amtDesktop.canvas.clearRect(0, 0, amtDesktop.canvasid.width, amtDesktop.canvasid.height); amtDesktop = null; }
            readState = 0;
            waitTimerArgs = null;
            currentDeltaTimeTotalSec = 0;
            recFileEndTime = 0;
            agentTerminal = null;
            if (waitTimer != null) { clearTimeout(waitTimer); waitTimer = null; }
            QH('srec_deskstatus', '');
            QE('srec_PlayButton', false);
            QE('srec_PauseButton', false);
            QE('srec_RestartButton', false);
            QS('srec_progressbar').width = '0px';
            QH('srec_timespan', '00:00:00');
            QV('srec_metadatadiv', true);
            QH('srec_metadatadiv', '<div style="width:100%;text-align:center;color:gray;margin-top:26px"><span style="font-size:20px">' + "Session Player registrato" + '</span><div style="margin:4px">' + "Trascina e rilascia un file .mcrec o fai clic su \"Apri file ...\"" + '</div></div>');
            QV('srec_DeskParent', false);
            QV('srec_TermParent', false);
            QV('srec_toggleviewmode', false);
        }

        function srec_ondrop(e) {
            haltEvent(e);

            // Check if these are files we can upload, remove all folders.
            if (e.dataTransfer == null) return;
            var files = [];
            for (var i in e.dataTransfer.files) {
                if ((e.dataTransfer.files[i].type != null) && (e.dataTransfer.files[i].size != null) && (e.dataTransfer.files[i].size != 0) && (e.dataTransfer.files[i].name.endsWith('.mcrec'))) {
                    files.push(e.dataTransfer.files[i]);
                }
            }
            if (files.length == 0) return;
            srec_cleanup();
            recFile = files[0];
            recFilePtr = 0;
            readNextBlock(processFirstBlock);
            readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
            srec_restart();
        }

        function srec_openfile() {
            var x = '<input type=file name=files id=srec_p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />';
            setDialogMode(11, "Apri il file...", 3, srec_openfileEx, x);
            QE('idx_dlgOkButton', false);
        }

        function srec_openfileEx() {
            var xfiles = Q('srec_p2fileinput').files;
            if (xfiles != null) { var files = []; for (var i in xfiles) { if ((xfiles[i].type != null) && (xfiles[i].size != null) && (xfiles[i].size != 0) && (xfiles[i].name.endsWith('.mcrec'))) { files.push(xfiles[i]); } } }
            if (files.length == 0) return;
            srec_cleanup();
            recFile = files[0];
            recFilePtr = 0;
            readNextBlock(processFirstBlock);
            readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
            Q('srec_OpenFileButton').blur();
        }

        function openfileChanged() {
            var xfiles = Q('srec_p2fileinput').files;
            if (xfiles != null) { var files = []; for (var i in xfiles) { if ((xfiles[i].type != null) && (xfiles[i].size != null) && (xfiles[i].size != 0) && (xfiles[i].name.endsWith('.mcrec'))) { files.push(xfiles[i]); } } }
            QE('idx_dlgOkButton', files.length == 1);
        }

        function srec_togglePause() {
            if (recFile != null) { if (srec_playing == 2) { srec_pause(); } else { if (recFilePtr != recFile.size) { srec_play(); } } } return false;
        }

        function srec_play() {
            Q('srec_PlayButton').blur();
            if ((srec_playing == 2) || (recFileProtocol == 0)) return;
            srec_playing = 2;
            QV('srec_metadatadiv', false);
            QE('srec_PlayButton', false);
            QE('srec_PauseButton', true);
            QE('srec_RestartButton', false);
            if ((recFileProtocol == 2) || (recFileProtocol == 101) || (recFileProtocol == 200)) {
                QV('srec_DeskParent', true);
                QV('srec_TermParent', false);
            } else if ((recFileProtocol == 1) && (agentTerminal == null)) {
                QV('srec_DeskParent', false);
                QV('srec_TermParent', true);
                agentTerminal = CreateAmtRemoteTerminal('srec_Term', {});
                agentTerminal.State = 3;
                agentTerminal.heightLock = 1;
            }
            readNextBlock(processBlock);
        }

        function srec_pause() {
            Q('srec_PauseButton').blur();
            if (srec_playing < 2) return;
            srec_playing = 1;
            QE('srec_PlayButton', recFilePtr != recFile.size);
            QE('srec_PauseButton', false);
            QE('srec_RestartButton', recFilePtr != 0);
            if (waitTimer != null) {
                clearTimeout(waitTimer);
                waitTimer = null;
                processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]);
                waitTimerArgs = null;
            }
        }

        function srec_restart() {
            Q('srec_RestartButton').blur();
            if (srec_playing == 0) return;
            recFilePtr = 0;
            readState = 0;
            currentDeltaTimeTotalSec = 0;
            QV('srec_metadatadiv', true);
            QE('srec_PlayButton', true);
            QE('srec_PauseButton', false);
            QE('srec_RestartButton', false);
            QS('srec_progressbar').width = '0px';
            QH('srec_timespan', '00:00:00');
            QV('srec_DeskParent', false);
            QV('srec_TermParent', false);
            if (agentDesktop) {
                agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height);
            }
            if (amtDesktop) {
                amtDesktop.canvas.clearRect(0, 0, amtDesktop.canvasid.width, amtDesktop.canvasid.height);
                amtDesktop = CreateAmtRemoteDesktop('srec_Desk');
                amtDesktop.onScreenSizeChange = srec_deskAdjust;
                amtDesktop.State = 3;
                amtDesktop.Start();
                if (recFileMetadata.protocol == 200) {
                    if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; }
                    if (recFileMetadata.graymode) { amtDesktop.graymode = recFileMetadata.graymode; }
                    if (recFileMetadata.lowcolor) { amtDesktop.lowcolor = recFileMetadata.lowcolor; }
                    amtDesktop.state = 3;
                    srec_deskAdjust();
                }
            }
            if (agentTerminal) { agentTerminal = null; }
        }

        function clearConsoleMsg() {
            //QH('srec_p11DeskConsoleMsg', '');
        }

        // Toggle the web page to full screen
        function srec_toggleAspectRatio(toggle) {
            if (toggle === 1) { srec_deskAspectRatio = ((srec_deskAspectRatio + 1) % 3); }
            srec_deskAdjust();
        }

        function srec_deskAdjust() {
            var parentH = Q('srec_DeskParent').clientHeight, parentW = Q('srec_DeskParent').clientWidth;
            var deskH = Q('srec_Desk').height, deskW = Q('srec_Desk').width;
            QS('srec_Desk')['margin-top'] = null;
            QS('srec_Desk')['margin-left'] = null;

            if (srec_deskAspectRatio == 2) {
                // Scale mode
                QS('srec_Desk')['margin-top'] = null;
                QS('srec_Desk').height = '100%';
                QS('srec_Desk').width = '100%';
                QS('srec_DeskParent').overflow = 'hidden';
            } else if (srec_deskAspectRatio == 1) {
                // Zoomed mode
                QS('srec_Desk')['margin-top'] = '0px';
                QS('srec_Desk').height = deskH + 'px';
                QS('srec_Desk').width = deskW + 'px';
                QS('srec_DeskParent').overflow = 'scroll';
            } else {
                // Fixed aspect ratio
                if ((parentH / parentW) > (deskH / deskW)) {
                    var hNew = ((deskH * parentW) / deskW) + 'px';
                    QS('srec_Desk').height = hNew;
                    QS('srec_Desk').width = '100%';
                    QS('srec_Desk')['margin-top'] = ((parentH - ((deskH * parentW) / deskW)) / 2) + 'px';
                } else {
                    var wNew = ((deskW * parentH) / deskH) + 'px';
                    QS('srec_Desk').height = '100%';
                    QS('srec_Desk').width = wNew;
                    QS('srec_Desk')['margin-left'] = ((parentW - ((deskW * parentH) / deskH)) / 2) + 'px'
                }
                QS('srec_DeskParent').overflow = 'hidden';
            }
        }

        function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }

        // ###END###{SessionRecording}

        //
        // POPUP DIALOG
        //

        // undefined = Hidden, 1 = Generic Message
        var xxdialogMode;
        var xxdialogFunc;
        var xxdialogButtons;
        var xxdialogTag;

        // Display a dialog box
        // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 11 only)
        function setDialogMode(x, y, b, f, c, tag) {
            xxdialogMode = x;
            xxdialogFunc = f;
            xxdialogButtons = b;
            xxdialogTag = tag;
            QE('idx_dlgOkButton', true);
            QV('idx_dlgOkButton', b & 1);
            QV('idx_dlgCancelButton', b & 2);
            QV('id_dialogclose', b & 2);
            QV('idx_dlgDeleteButton', b & 4);
            if (y) QH('id_dialogtitle', y);
            for (var i = 1; i < 28; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
            QV('dialog', x);
            if (c) { if (x == 11) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }

            // ###BEGIN###{IDERStats}
            if (xxdialogMode != 0) { iderToggleDiskMap(false); }
            // ###END###{IDERStats}
        }

        function dialogclose(x) {
            var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
            setDialogMode();
            if (((b & 8) || x) && f) f(x, t);
        }

        function center() {
            QS('dialog').left = ((((getDocWidth() - 400) / 2)) + 'px');
            // ###BEGIN###{Desktop}
            var sh = 0, mh = (Q('id_mainarea').offsetHeight - ((fullscreen == false)?126:53));
            // ###BEGIN###{Scripting}
            if (QS('id_scriptstatus').display == '') sh += 32; // If script status is displayed, reduce max-height by 22 pixels
            // ###END###{Scripting}
            // ###BEGIN###{IDER}
            if (QS('id_iderstatus').display == '') sh += 32; // If ider status is displayed, reduce max-height by 22 pixels
            // ###END###{IDER}
            QS('id_mainarea_pad').height = (Q('id_mainarea').offsetHeight - sh - ((fullscreen == false)?16:0)) + 'px';
            QS('Desk')['max-height'] =  (mh - sh) + 'px';
            QS('Desk')['max-width'] = (Q('id_mainarea').offsetWidth - ((fullscreen == false)?32:0)) + 'px';
            if (Q('id_DeskParent').offsetWidth != 0) { QS('Desk')['max-width'] = Q('id_DeskParent').offsetWidth; }
            if (fullscreen) {
                QS('id_mainarea_pad')['overflow-y'] = 'hidden';
                var h = (mh - sh - Q('Desk').offsetHeight) / 2;
                QS('Desk')['margin-top'] = h + 'px';
                QS('Desk')['margin-bottom'] = h + 'px';
            } else {
                QS('id_mainarea_pad')['overflow-y'] = 'scroll';
                QS('Desk')['margin-top'] = '0';
                QS('Desk')['margin-bottom'] = '0';
            }
            // ###END###{Desktop}
            // ###BEGIN###{Storage}
            //QS('id_mainarea_frame').height = Q('id_mainarea').offsetHeight;
            // ###END###{Storage}

            // ###BEGIN###{SessionRecording}
            srec_deskAdjust();
            // ###END###{SessionRecording}
        }
        function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
        function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }

        //
        // GENERIC METHODS
        //

        // ###BEGIN###{FileSaver}
        function SaveJsonFile(name, name2, desc, data) {
            var n = '', r = {}, d = new Date();
            if (amtsysstate) {
                n = '-' + amtsysstate['AMT_GeneralSettings'].response['HostName'];
                r = {'webappversion':version,'description':desc,'hostname':amtsysstate['AMT_GeneralSettings'].response['HostName'],'localtime':Date(),'utctime':new Date().toUTCString(),'isotime':new Date().toISOString()};
                if (HardwareInventory) r['systemid'] = guidToStr(HardwareInventory['CIM_ComputerSystemPackage'].response['PlatformGUID'].toLowerCase());
            }
            n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);;
            r[name2] = data;
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(JSON.stringify(r, null, '  ').replace(/\n/g, '\r\n')), name + n + '.json');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', name + n + '.json');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, JSON.stringify(r, null, '  ').replace(/\n/g, '\r\n'), function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        var httpErrorTable = {
            200: "ok",
            401: "Errore di autenticazione",
            408: "Errore di timeout",
            601: "Errore di analisi WSMAN",
            602: "Impossibile analizzare l'intestazione della risposta HTTP",
            603: "Risposta enum HTTP inattesa",
            604: "Risposta pull HTTP inaspettata",
            // ###BEGIN###{Mode-NodeWebkit}
            998: "Certificato TLS non valido",
            // ###END###{Mode-NodeWebkit}
            997: "Digest Realm non valido"
        }
        function errcheck(s, stack) {
            if (wsstack == null || amtstack != stack) return true;
            if (s != 200 && s != 9) {
                setDialogMode();
                wsstack.comm.FailAllError = 999; // Cause all new responses to be silent
                amtstack.CancelAllQueries(999);
                QH('id_messageviewstr', ((httpErrorTable[s])?(httpErrorTable[s]):(format("Errore # {0}", s))));
                // ###BEGIN###{Mode-MeshCentral2}
                if (s == 401) { QH('id_messageviewstr', "Errore di autenticazione" + '<br /><br /><input type=button value=\"' + "Set new credentials" + '\" onclick=meshcentral2credCallback(true)></input>'); }
                // ###END###{Mode-MeshCentral2}
                go(100);
                QS('id_progressbar').width = 0;
                // ###BEGIN###{ComputerSelector}
                Q('id_messageviewbutton').focus();
                // ###END###{ComputerSelector}

                // ###BEGIN###{Mode-NodeWebkit}
                if (s == 998) {
                    //console.log('errcheck', wsstack.comm.xtlsCertificate.fingerprint);
                    if (wsstack.comm.xtlsCertificate != null) {
                        showTlsCert(11, '<img style=float:left;margin-right:8px src=warning.png width=48 height=48><div style=min-height:48px;display:table><div style=display:table-cell;vertical-align:middle>' + "Intel&reg; AMT collegato con il seguente certificato. Premere Annulla per disconnettersi se questo non è il certificato previsto." + '</div></div>', wsstack.comm.xtlsCertificate, 1);
                    }
                }
                // ###END###{Mode-NodeWebkit}
            }
            return (s != 200);
        }

        // ###BEGIN###{Storage}
        function goiFrame(e,x,y) {
            if (xxdialogMode) return;
            go(x);
            // ###BEGIN###{Mode-NodeWebkit}
            var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
            y = (currentcomputer['tls']==0?'http://':'https://') + ports.host + ':' + ports.http + y;
            // ###END###{Mode-NodeWebkit}
            if ((e.shiftKey == true) || (Q('id_StorageIFrame').src.endsWith(y) == false)) Q('id_StorageIFrame').src = y;
            QV('id_mainarea_pad', false);
            QV('id_mainarea_frame', true);
        }
        // ###END###{Storage}

        function go(x, force) {
            if (xxdialogMode && force != 1) return;
            // ###BEGIN###{Mode-NodeWebkit}
            // Remove left bar selection
            var leftBarItems = ['LeftMenuMyDevices', 'LeftMenuMyCerts', 'LeftMenuMyUsb'];
            // ###BEGIN###{SessionRecording}
            leftBarItems.push('LeftMenuPlayer');
            // ###END###{SessionRecording}
            for (var i in leftBarItems) { Q(leftBarItems[i]).classList.remove('lbbuttonsel'); Q(leftBarItems[i]).classList.remove('lbbuttonsel2'); }
            if (x == 101) { Q('LeftMenuMyDevices').classList.add('lbbuttonsel2'); }
            if (x == 103) { Q('LeftMenuMyCerts').classList.add('lbbuttonsel2'); }
            if (x == 102) { Q('LeftMenuMyUsb').classList.add('lbbuttonsel2'); }
            if (x == 104) { Q('LeftMenuPlayer').classList.add('lbbuttonsel2'); }
            QV('LeftSideToolBar', ((x >= 101) && (x <= 104)));
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Storage}
            QV('id_mainarea_frame', false);
            QV('id_mainarea_pad', true);
            // ###END###{Storage}
            // ###BEGIN###{ComputerSelector}
            QV('id_computerSelector', x == 101);
            // ###END###{ComputerSelector}
            // ###BEGIN###{Mode-LMS}
            QV('id_lmsMainPanel', x == 101);
            // ###END###{Mode-LMS}
            // ###BEGIN###{USBSetup}
            QV('id_usbSetupPanel', x == 102);
            // ###END###{USBSetup}
            // ###BEGIN###{CertificateManager}
            QV('id_certManagerPanel', x == 103);
            // ###END###{CertificateManager}
            // ###BEGIN###{SessionRecording}
            QV('id_sessionPlayerPanel', x == 104);
            // ###END###{SessionRecording}
            QV('id_messageview', x == 100);
            QV('id_mainview', x < 100);
            for (var i = 0; i < 80; i++) { // Edit this line when adding a new screen
                QV('p' + i, i == x);
                var q = QS('go' + i);
                // ###BEGIN###{Look-Intel}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-Intel}
                // ###BEGIN###{Look-ISDU}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-ISDU}
                // ###BEGIN###{Look-BrandedCommander}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-BrandedCommander}
                // ###BEGIN###{Look-Unite}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-Unite}
                // ###BEGIN###{Look-Commander}
                if (q) { q['background-color'] = ((i == x)?'gray':''); }
                // ###END###{Look-Commander}
                // ###BEGIN###{Look-MeshCentral}
                if (q) { q['background-color'] = ((i == x)?'gray':''); }
                // ###END###{Look-MeshCentral}
            }
            currentView = x;
            // ###BEGIN###{Look-ISDU}
            QV('id_isdu-image1', x == 11);
            QV('id_isdu-image2', x == 8);
            QV('id_isdu-image3', x == 14 || x == 13);
            QV('id_isdu-image4', x == 1 || x == 0);
            QV('id_isdu-image5', x == 6 || x == 15);
            QV('id_isdu-image6', x == 18 || x == 19);
            QV('id_isdu-image7', x == 16 || x == 12 || x == 2);
            QV('id_isdu-image8', x == 17);
            // ###END###{Look-ISDU}
            // ###BEGIN###{Look-BrandedCommander}
            // ###BEGIN###{!Mode-Firmware}
            QV('id_isdu-image1', x == 11);
            QV('id_isdu-image2', x == 8);
            QV('id_isdu-image3', x == 14 || x == 13);
            QV('id_isdu-image4', x == 1 || x == 0);
            QV('id_isdu-image5', x == 6 || x == 15);
            QV('id_isdu-image6', x == 18 || x == 19);
            QV('id_isdu-image7', x == 16 || x == 12 || x == 2);
            QV('id_isdu-image8', x == 17);
            // ###END###{!Mode-Firmware}
            // ###END###{Look-BrandedCommander}
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(x);
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Desktop}
            center();
            // ###END###{Desktop}
        }

        function portsFromHost(host, tls) {
            host = decodeURIComponent(host);
            var x = host.split(':'), hp = ((tls == 0) ? 16992 : 16993), rp = ((tls == 0) ? 16994 : 16995);
            if (x[0].indexOf('[') == 0) { // IPv6 address
                x = host.split(']:');
                if (x.length == 1) { return { host: host.substring(1, host.length - 1), http: hp, redir: rp } }
                if (x.length > 1) { var y = x[1].split(':'); if (y.length > 0) { hp = parseInt(y[0]); } if (y.length > 1) { rp = parseInt(y[1]); } }
                return { host: x[0].substring(1), http: hp, redir: rp }
            }
            if (x.length > 1) { hp = parseInt(x[1]); }
            if (x.length > 2) { rp = parseInt(x[2]); }
            return { host: x[0], http: hp, redir: rp }
        }
        function addLink(x, f) { return '<a style=cursor:pointer;color:blue onclick=\'' + f + '\'>&diams; ' + x + '</a>'; }
        function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
        function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
        function addOption(q, t, i) { var option = document.createElement('option'); option.text = t; option.value = i; Q(q).add(option); }
        function addDisabledOption(q, t, i) { var option = document.createElement('option'); option.text = t; option.value = i; option.disabled = 1; Q(q).add(option); }
        function passwordcheck(p) { if (p.length < 8) return false; var upper = 0, lower = 0, number = 0, nonalpha = 0; for (var i in p) { var c = p.charCodeAt(i); if ((c > 64) && (c < 91)) { upper = 1; } else if ((c > 96) && (c < 123)) { lower = 1; } else if ((c > 47) && (c < 58)) { number = 1; } else { nonalpha = 1; } } return ((upper + lower + number + nonalpha) == 4); }
        function methodcheck(r) { if (r && r != null && r.Body && r.Body['ReturnValue'] != 0) { messagebox("Errore di chiamata", r.Header['Method'] + ': ' + (r.Body.ReturnValueStr + '').replace('_', ' ')); return true; } return false; }
        function TableStart() { return '<table class=\'log1 us\' cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=200px><p><td>'; }
        function TableStart2() { return '<table class=\'log1 us\' cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td>'; }
        function TableEntry(n, v) { return '<tr><td class=r1><p>' + n + '<td class=r1>' + v; }
        function FullTable(x, e) { var r = TableStart(); for (i in x) { if (i && x[i]) r += TableEntry(i, x[i]); } return r + TableEnd(e); }
        function TableEnd(n) { return '<tr><td colspan=2><p>' + (n?n:'') + '</table>'; }
        function AddButton(v, f) { return '<input type=button value=\'' + v + '\' onclick=\'' + f + '\' style=margin:4px>'; }
        function AddButton2(v, f, s) { return '<input type=button value=\'' + v + '\' onclick=\'' + f + '\' ' + s + '>'; }
        function AddRefreshButton(f) { return '<input type=button name=refreshbtn value="' + "ricaricare" + '" onclick=\'refreshButtons(false);' + f + '\' style=margin:4px ' + (refreshButtonsState==false?'disabled':'') + '>'; }
        function MoreStart() { return '<a style=cursor:pointer;color:blue id=morexxx1 onclick=QV(\"morexxx1\",false);QV(\"morexxx2\",true)>&#x25BC; ' + "More" + '</a><div id=morexxx2 style=display:none><br><hr>'; };
        function MoreEnd() { return '<a style=cursor:pointer;color:blue onclick=QV(\"morexxx2\",false);QV(\"morexxx1\",true)>&#x25B2; ' + "Less" + '</a></div>'; };
        function getSelectedOptions(sel) { var opts = [], opt; for (var i = 0, len = sel.options.length; i < len; i++) { opt = sel.options[i]; if (opt.selected) { opts.push(opt.value); } } return opts; }
        function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; }
        function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
        function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + '-' + g.substring(10, 12) + g.substring(8, 10) + '-' + g.substring(14, 16) + g.substring(12, 14) + '-' + g.substring(16, 20) + '-' + g.substring(20); }
        function getUrlVars() { var j, hash, vars = [], hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { j = hashes[i].indexOf('='); if (j > 0) { vars[hashes[i].substring(0, j)] = hashes[i].substring(j + 1, hashes[i].length); } } return vars; }
        function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
        function getDocHeight() { if (window.innerHeight) return window.innerHeight; if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientHeight != 0) return document.documentElement.clientHeight; return document.getElementsByTagName('body')[0].clientHeight; }
        function addHtmlValue(t, v) { return '<div style=height:20px><div style=float:right;width:220px;overflow:hidden><b title="' + v + '">' + v + '</b></div><div>' + t + '</div></div>'; }
        function addHtmlValueNoTitle(t, v) { return '<div style=height:20px><div style=float:right;width:220px;overflow:hidden>' + v + '</b></div><div>' + t + '</div></div>'; }
        function numbersOnly(e, x) { return (event.charCode == 0) || (event.charCode == x) || (event.charCode >= 48 && event.charCode <= 57); }
        function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };

// ###BEGIN###{**ClosureAdvancedMode}
        // Google closure advanced mode externs
        window['cleanup'] = cleanup;
        window['disconnect'] = disconnect;
        window['dialogclose'] = dialogclose;
        window['go'] = go;
        window['QV'] = QV;
        window['numbersOnly'] = numbersOnly;
        window['syncClock'] = syncClock;
        window['showLinkPolicyDlg'] = showLinkPolicyDlg;
        // ###BEGIN###{PowerControl}
        window['showPowerActionDlg'] = showPowerActionDlg;
        // ###BEGIN###{PowerControl-Advanced}
        window['showAdvPowerDlg'] = showAdvPowerDlg;
        window['showAdvPowerDlgChange'] = showAdvPowerDlgChange;
        // ###END###{PowerControl-Advanced}
        // ###END###{PowerControl}
        window['showFeaturesDlg'] = showFeaturesDlg;
        window['showConsentDlg'] = showConsentDlg;
        // ###BEGIN###{NetworkSettings}
        window['showPingActionDlg'] = showPingActionDlg;
        window['showIPSetupDlg'] = showIPSetupDlg;
        window['updateIPSetupDlg'] = updateIPSetupDlg;
        window['showIPv6StateDlg'] = showIPv6StateDlg;
        window['showIPv6AddrDlg'] = showIPv6AddrDlg;
        // ###END###{NetworkSettings}
        window['PullSystemStatus'] = PullSystemStatus;
        window['changeAccountButton'] = changeAccountButton;
        window['changeAccountStateButton'] = changeAccountStateButton;
        window['newAccountButton'] = newAccountButton;
        window['showUserDetails'] = showUserDetails;
        window['showEditDnsDlg'] = showEditDnsDlg;
        window['showEditDnsDlgChange'] = showEditDnsDlgChange;
        window['setDialogMode'] = setDialogMode;
        window['PullUserInfo'] = PullUserInfo;
        window['toggleAccountButton'] = toggleAccountButton;
        window['showEditNameDlg'] = showEditNameDlg;
        window['updateAccountDialog'] = updateAccountDialog;
        window['refreshButtons'] = refreshButtons;
        window['showPowerPolicyDlg'] = showPowerPolicyDlg;
        // ###BEGIN###{HardwareInfo}
        window['PullHardware'] = PullHardware;
        // ###BEGIN###{FileSaver}
        window['SaveHardwareLog'] = SaveHardwareLog;
        // ###END###{FileSaver}
        // ###END###{HardwareInfo}
        // ###BEGIN###{WsmanBrowser}
        // ###BEGIN###{FileSaver}
        window['saveEntireAmtState'] = saveEntireAmtState;
        // ###END###{FileSaver}
        // ###END###{WsmanBrowser}
        // ###BEGIN###{ContextMenus}
        window['handleContextMenu'] = handleContextMenu;
        window['hideContextMenu'] = hideContextMenu;
        // ###END###{ContextMenus}
        // ###BEGIN###{Mode-NodeWebkit}
        window['showTlsCert'] = showTlsCert;
        window['downloadTlsCert'] = downloadTlsCert;
        // ###END###{Mode-NodeWebkit}

        // ###BEGIN###{Desktop}
        window['connectDesktopButton'] = connectDesktopButton;
        window['connectDesktop'] = connectDesktop;
        window['deskToggleFull'] = deskToggleFull;
        window['showDesktopSettings'] = showDesktopSettings;
        window['dmousedown'] = dmousedown;
        window['dmouseup'] = dmouseup;
        window['dmousemove'] = dmousemove;
        window['drotate'] = drotate;
        window['sendCAD'] = sendCAD;
        // ###BEGIN###{FileSaver}
        window['deskSaveImage'] = deskSaveImage;
        // ###END###{FileSaver}
        // ###BEGIN###{DesktopFocus}
        window['deskToggleFocus'] = deskToggleFocus;
        // ###END###{DesktopFocus}
        // ###BEGIN###{Desktop-Multi}
        window['desktopSwitchScreen'] = desktopSwitchScreen;
        // ###END###{Desktop-Multi}
        // ###END###{Desktop}

        // ###BEGIN###{Desktop-Settings}
        window['showDesktopSettingsDlg'] = showDesktopSettingsDlg;
        window['showDesktopSettingsDlgUpdate'] = showDesktopSettingsDlgUpdate;
        // ###END###{Desktop-Settings}

        // ###BEGIN###{Terminal}
        window['connectTerminal'] = connectTerminal;
        window['termPaste'] = termPaste;
        window['termSendKey'] = termSendKey;
        // ###BEGIN###{FileSaver}
        window['terminalCaptureToggle'] = terminalCaptureToggle;
        // ###END###{FileSaver}
        // ###BEGIN###{TerminalSize}
        window['termToggleSize'] = termToggleSize;
        // ###END###{TerminalSize}
        window['termToggleFx'] = termToggleFx;
        // ###BEGIN###{Terminal-Enumation-All}
        window['termToggleType'] = termToggleType;
        // ###END###{Terminal-Enumation-All}
        window['termPaste'] = termPaste;
        // ###END###{Terminal}

        // ###BEGIN###{IDER}
        window['iderStart'] = iderStart;
        window['iderStop'] = iderStop;
        // ###BEGIN###{IDERStats}
        window['iderToggleDiskMap'] = iderToggleDiskMap;
        // ###END###{IDERStats}
        // ###END###{IDER}

        // ###BEGIN###{RemoteAccess}
        window['editEnvironmentDetection'] = editEnvironmentDetection;
        window['editEnvironmentDetectionAdd'] = editEnvironmentDetectionAdd;
        window['editUserInitiatedCira'] = editUserInitiatedCira;
        window['editMpsPolicy'] = editMpsPolicy;
        window['showServerDetails'] = showServerDetails;
        window['AddRemoteAccessServer'] = AddRemoteAccessServer;
        window['AddRemoteAccessServerUpdate'] = AddRemoteAccessServerUpdate;
        window['edInputChg'] = edInputChg;
        window['editMpsPolicyUpdate'] = editMpsPolicyUpdate;
        window['editEnvironmentDetectionRemove'] = editEnvironmentDetectionRemove;
        // ###END###{RemoteAccess}

        // ###BEGIN###{EventLog}
        window['showEventDetails'] = showEventDetails;
        window['PullEventLog'] = PullEventLog;
        window['FreezeLog'] = FreezeLog;
        window['ClearLog'] = ClearLog;
        window['eventFilter'] = eventFilter;
        // ###BEGIN###{FileSaver}
        window['SaveEventLog'] = SaveEventLog;
        // ###END###{FileSaver}
        // ###END###{EventLog}

        // ###BEGIN###{AuditLog}
        window['PullAuditLog'] = PullAuditLog;
        window['auditFilter'] = auditFilter;
        window['showAuditDetails'] = showAuditDetails;
        // ###BEGIN###{FileSaver}
        window['SaveAuditLog'] = SaveAuditLog;
        // ###END###{FileSaver}
        // ###END###{AuditLog}

        // ###BEGIN###{Certificates}
        window['PullCertificates'] = PullCertificates;
        window['showCertDetails'] = showCertDetails;
        window['addCertButton'] = addCertButton;
        window['issueCertButton'] = issueCertButton;
        window['showSetTlsSecurityDlg'] = showSetTlsSecurityDlg;
        window['showSetTlsSecurityDlgUpdate'] = showSetTlsSecurityDlgUpdate;
        window['showKeyPairDetails'] = showKeyPairDetails;
        window['addCertButtonUpdate'] = addCertButtonUpdate;
        window['issueCertButtonUpdate'] = issueCertButtonUpdate;
        // ###BEGIN###{FileSaver}
        window['downloadCert'] = downloadCert;
        // ###END###{FileSaver}
        // ###END###{Certificates}

        // ###BEGIN###{AgentPresence}
        window['addWatchdogAction'] = addWatchdogAction;
        window['deleteWatchdogActions'] = deleteWatchdogActions;
        window['PullWatchdog'] = PullWatchdog;
        window['AddWatchdog'] = AddWatchdog;
        window['AddWatchdogUpdate'] = AddWatchdogUpdate;
        window['addWatchdogActionUpdate'] = addWatchdogActionUpdate;
        window['showWatchdogDetails'] = showWatchdogDetails;
        window['GenerateWatchdogGuid'] = GenerateWatchdogGuid;
        // ###END###{AgentPresence}

        // ###BEGIN###{SystemDefense}
        window['changeDefaultPolicy'] = changeDefaultPolicy;
        window['AddDefenseFilter'] = AddDefenseFilter;
        window['AddDefenseFilterUpdate'] = AddDefenseFilterUpdate;
        window['showFilterDetails'] = showFilterDetails;
        window['AddDefensePolicy'] = AddDefensePolicy;
        window['addFilterButton'] = addFilterButton;
        window['removeFilterButton'] = removeFilterButton;
        window['AddDefensePolicyUpdate'] = AddDefensePolicyUpdate;
        window['showPolicyDetails'] = showPolicyDetails;
        window['deleteDefensePolicy'] = deleteDefensePolicy;
        // ###END###{SystemDefense}

        // ###BEGIN###{Wireless}
        window['showWifiStateDlg'] = showWifiStateDlg;
        window['showWifiDetails'] = showWifiDetails;
        window['wifiRemoveButton'] = wifiRemoveButton;
        window['showWifiNewProfile'] = showWifiNewProfile;
        window['updateWifiDialog'] = updateWifiDialog;
        window['wifiRefresh'] = wifiRefresh;
        // ###END###{Wireless}

        // ###BEGIN###{WsmanBrowser}
        window['wsmanQuery'] = wsmanQuery;
        window['wsmanFilter'] = wsmanFilter;
        window['QH'] = QH;
        window['QV'] = QV;
        // ###END###{WsmanBrowser}
        
        // ###BEGIN###{Alarms}
        window['PullAlarms'] = PullAlarms;
        window['RemoveAllAlarms'] = RemoveAllAlarms;
        window['showAddAlarm'] = showAddAlarm;
        window['showAlertDetails'] = showAlertDetails;
        window['alertDialogUpdate'] = alertDialogUpdate;
        // ###END###{Alarms}

        // ###BEGIN###{ComputerSelector}
        window['computerConnect'] = computerConnect;
        window['toolmenuclick'] = toolmenuclick;
        window['computerFilterFunc'] = computerFilterFunc;
        window['computerSelect'] = computerSelect;
        
        // ###BEGIN###{ComputerSelector-Local}
        window['updateComputerDialog'] = updateComputerDialog;
        window['computerEdit'] = computerEdit;
        window['addComputer'] = addComputer;
        window['newComputerList'] = newComputerList;
        window['openComputerList'] = openComputerList;
        window['saveComputerList'] = saveComputerList;
        // ###END###{ComputerSelector-Local}

        // ###BEGIN###{Scripting}
        window['computerStopScript'] = computerStopScript;
        window['mscript_runScriptDlg'] = mscript_runScriptDlg;
        window['onComputerChecked'] = onComputerChecked;
        window['mscript_showComputerScriptOutput'] = mscript_showComputerScriptOutput;
        // ###END###{Scripting}

        // ###BEGIN###{ComputerSelectorScanner}
        // ###BEGIN###{Mode-NodeWebkit}
        window['showScanDialog'] = showScanDialog;
        window['showScanDialogUpdate'] = showScanDialogUpdate;
        // ###END###{Mode-NodeWebkit}
        // ###END###{ComputerSelectorScanner}

        // ###END###{ComputerSelector}

        // ###BEGIN###{Mode-LMS}
        window['lmsRefresh'] = lmsRefresh;
        window['lmsConfigure'] = lmsConfigure;
        window['lmsLogin'] = lmsLogin;
        window['lmsConfigureLogin'] = lmsConfigureLogin;
        window['lmsUpdateLoginDialog'] = lmsUpdateLoginDialog;
        window['lmsShowVersionsDlg'] = lmsShowVersionsDlg;
        window['lmsActivate'] = lmsActivate;
        window['lmsDeactivate'] = lmsDeactivate;
        window['toolmenuclick'] = toolmenuclick;
        window['lmsShowTrustedHashesDlg'] = lmsShowTrustedHashesDlg;
        // ###END###{Mode-LMS}

        // ###BEGIN###{Storage}
        window['SetStorageName'] = SetStorageName;
        window['showStorageDetails'] = showStorageDetails;
        window['PullStorage'] = PullStorage;
        window['UploadToStorage'] = UploadToStorage;
        window['goiFrame'] = goiFrame;
        // ###BEGIN###{Mode-Firmware}
        window['OpenFromStorage'] = OpenFromStorage;
        // ###END###{Mode-Firmware}
        // ###BEGIN###{Mode-LMS}
        window['OpenFromStorage'] = OpenFromStorage;
        // ###END###{Mode-LMS}
        // ###BEGIN###{FileSaver}
        window['DownloadFromStorage'] = DownloadFromStorage;
        // ###END###{FileSaver}
        // ###BEGIN###{Mode-NodeWebkit}
        window['UploadAppToStorage'] = UploadAppToStorage;
        // ###END###{Mode-NodeWebkit}
        // ###END###{Storage}

        // ###BEGIN###{Scripting}
        window['script_runScriptDlg'] = script_runScriptDlg;
        window['script_Stop'] = script_Stop;
        // ###END###{Scripting}

        // ###BEGIN###{Scripting-Editor}
        // ###BEGIN###{FileSaver}
        window['script_saveScript'] = script_saveScript;
        // ###END###{FileSaver}
        window['resetScriptButton'] = resetScriptButton;
        window['runScriptButton'] = runScriptButton;
        window['breakScriptButton'] = breakScriptButton;
        window['stepScriptButton'] = stepScriptButton;
        window['scriptViewButton'] = scriptViewButton;
        window['script_fonfilterchanged'] = script_fonfilterchanged;
        window['script_fonclick'] = script_fonclick;
        window['script_fondragstart'] = script_fondragstart;
        window['script_fondragend'] = script_fondragend;
        window['script_fondragenter'] = script_fondragenter;
        window['script_fondragleave'] = script_fondragleave;
        window['script_fondrop'] = script_fondrop;
        window['script_foneditclick'] = script_foneditclick;
        window['script_foneditclickEx'] = script_foneditclickEx;
        // ###END###{Scripting-Editor}

        // ###BEGIN###{USBSetup}
        window['usb_newSetupBin'] = usb_newSetupBin;
        window['usb_openSetupBin'] = usb_openSetupBin;
        window['usb_addRecordSetupBin'] = usb_addRecordSetupBin;
        window['usb_addvariable'] = usb_addvariable;
        window['usb_editheader'] = usb_editheader;
        window['usb_editrecord'] = usb_editrecord;
        window['usb_editvariable'] = usb_editvariable;
        window['usb_ond16typechange'] = usb_ond16typechange;
        // ###BEGIN###{FileSaver}
        window['usb_saveSetupBin'] = usb_saveSetupBin;
        // ###END###{FileSaver}
        // ###END###{USBSetup}

        // ###BEGIN###{Mode-MeshCentral2}
        window['connectButtonfunction'] = connectButtonfunction;
        // ###END###{Mode-MeshCentral2}

// ###END###{**ClosureAdvancedMode}

        // Get things started
        startup();
    </script>


</div></div></body></html>